@@ -56,6 +56,7 @@ module ts {
56
56
var globalBooleanType : ObjectType ;
57
57
var globalRegExpType : ObjectType ;
58
58
59
+ var tupleTypes : Map < TupleType > = { } ;
59
60
var stringLiteralTypes : Map < StringLiteralType > = { } ;
60
61
61
62
var fullTypeCheck = false ;
@@ -619,15 +620,13 @@ module ts {
619
620
}
620
621
621
622
function isOptionalProperty ( propertySymbol : Symbol ) : boolean {
622
- if ( propertySymbol . flags & SymbolFlags . Prototype ) {
623
- return false ;
624
- }
625
623
// class C {
626
624
// constructor(public x?) { }
627
625
// }
628
626
//
629
627
// x is an optional parameter, but it is a required property.
630
- return ( propertySymbol . valueDeclaration . flags & NodeFlags . QuestionMark ) && propertySymbol . valueDeclaration . kind !== SyntaxKind . Parameter ;
628
+ return propertySymbol . valueDeclaration && propertySymbol . valueDeclaration . flags & NodeFlags . QuestionMark &&
629
+ propertySymbol . valueDeclaration . kind !== SyntaxKind . Parameter ;
631
630
}
632
631
633
632
function forEachSymbolTableInScope < T > ( enclosingDeclaration : Node , callback : ( symbolTable : SymbolTable ) => T ) : T {
@@ -843,6 +842,9 @@ module ts {
843
842
else if ( type . flags & ( TypeFlags . Class | TypeFlags . Interface | TypeFlags . Enum | TypeFlags . TypeParameter ) ) {
844
843
writer . writeSymbol ( type . symbol , enclosingDeclaration , SymbolFlags . Type ) ;
845
844
}
845
+ else if ( type . flags & TypeFlags . Tuple ) {
846
+ writeTupleType ( < TupleType > type ) ;
847
+ }
846
848
else if ( type . flags & TypeFlags . Anonymous ) {
847
849
writeAnonymousType ( < ObjectType > type , allowFunctionOrConstructorTypeLiteral ) ;
848
850
}
@@ -855,6 +857,15 @@ module ts {
855
857
}
856
858
}
857
859
860
+ function writeTypeList ( types : Type [ ] ) {
861
+ for ( var i = 0 ; i < types . length ; i ++ ) {
862
+ if ( i > 0 ) {
863
+ writer . write ( ", " ) ;
864
+ }
865
+ writeType ( types [ i ] , /*allowFunctionOrConstructorTypeLiteral*/ true ) ;
866
+ }
867
+ }
868
+
858
869
function writeTypeReference ( type : TypeReference ) {
859
870
if ( type . target === globalArrayType && ! ( flags & TypeFormatFlags . WriteArrayAsGenericType ) ) {
860
871
// If we are writing array element type the arrow style signatures are not allowed as
@@ -865,16 +876,17 @@ module ts {
865
876
else {
866
877
writer . writeSymbol ( type . target . symbol , enclosingDeclaration , SymbolFlags . Type ) ;
867
878
writer . write ( "<" ) ;
868
- for ( var i = 0 ; i < type . typeArguments . length ; i ++ ) {
869
- if ( i > 0 ) {
870
- writer . write ( ", " ) ;
871
- }
872
- writeType ( type . typeArguments [ i ] , /*allowFunctionOrConstructorTypeLiteral*/ true ) ;
873
- }
879
+ writeTypeList ( type . typeArguments ) ;
874
880
writer . write ( ">" ) ;
875
881
}
876
882
}
877
883
884
+ function writeTupleType ( type : TupleType ) {
885
+ writer . write ( "[" ) ;
886
+ writeTypeList ( type . elementTypes ) ;
887
+ writer . write ( "]" ) ;
888
+ }
889
+
878
890
function writeAnonymousType ( type : ObjectType , allowFunctionOrConstructorTypeLiteral : boolean ) {
879
891
// Always use 'typeof T' for type of class, enum, and module objects
880
892
if ( type . symbol && type . symbol . flags & ( SymbolFlags . Class | SymbolFlags . Enum | SymbolFlags . ValueModule ) ) {
@@ -1649,6 +1661,23 @@ module ts {
1649
1661
return [ createSignature ( undefined , classType . typeParameters , emptyArray , classType , 0 , false , false ) ] ;
1650
1662
}
1651
1663
1664
+ function createTupleTypeMemberSymbols ( memberTypes : Type [ ] ) : SymbolTable {
1665
+ var members : SymbolTable = { } ;
1666
+ for ( var i = 0 ; i < memberTypes . length ; i ++ ) {
1667
+ var symbol = < TransientSymbol > createSymbol ( SymbolFlags . Property | SymbolFlags . Transient , "" + i ) ;
1668
+ symbol . type = memberTypes [ i ] ;
1669
+ members [ i ] = symbol ;
1670
+ }
1671
+ return members ;
1672
+ }
1673
+
1674
+ function resolveTupleTypeMembers ( type : TupleType ) {
1675
+ var arrayType = resolveObjectTypeMembers ( createArrayType ( getBestCommonType ( type . elementTypes ) ) ) ;
1676
+ var members = createTupleTypeMemberSymbols ( type . elementTypes ) ;
1677
+ addInheritedMembers ( members , arrayType . properties ) ;
1678
+ setObjectTypeMembers ( type , members , arrayType . callSignatures , arrayType . constructSignatures , arrayType . stringIndexType , arrayType . numberIndexType ) ;
1679
+ }
1680
+
1652
1681
function resolveAnonymousTypeMembers ( type : ObjectType ) {
1653
1682
var symbol = type . symbol ;
1654
1683
var members = emptySymbols ;
@@ -1682,6 +1711,9 @@ module ts {
1682
1711
else if ( type . flags & TypeFlags . Anonymous ) {
1683
1712
resolveAnonymousTypeMembers ( < ObjectType > type ) ;
1684
1713
}
1714
+ else if ( type . flags & TypeFlags . Tuple ) {
1715
+ resolveTupleTypeMembers ( < TupleType > type ) ;
1716
+ }
1685
1717
else {
1686
1718
resolveTypeReferenceMembers ( < TypeReference > type ) ;
1687
1719
}
@@ -2123,6 +2155,24 @@ module ts {
2123
2155
return links . resolvedType ;
2124
2156
}
2125
2157
2158
+ function createTupleType ( elementTypes : Type [ ] ) {
2159
+ var id = getTypeListId ( elementTypes ) ;
2160
+ var type = tupleTypes [ id ] ;
2161
+ if ( ! type ) {
2162
+ type = tupleTypes [ id ] = < TupleType > createObjectType ( TypeFlags . Tuple ) ;
2163
+ type . elementTypes = elementTypes ;
2164
+ }
2165
+ return type ;
2166
+ }
2167
+
2168
+ function getTypeFromTupleTypeNode ( node : TupleTypeNode ) : Type {
2169
+ var links = getNodeLinks ( node ) ;
2170
+ if ( ! links . resolvedType ) {
2171
+ links . resolvedType = createTupleType ( map ( node . elementTypes , t => getTypeFromTypeNode ( t ) ) ) ;
2172
+ }
2173
+ return links . resolvedType ;
2174
+ }
2175
+
2126
2176
function getTypeFromTypeLiteralNode ( node : TypeLiteralNode ) : Type {
2127
2177
var links = getNodeLinks ( node ) ;
2128
2178
if ( ! links . resolvedType ) {
@@ -2172,6 +2222,8 @@ module ts {
2172
2222
return getTypeFromTypeQueryNode ( < TypeQueryNode > node ) ;
2173
2223
case SyntaxKind . ArrayType :
2174
2224
return getTypeFromArrayTypeNode ( < ArrayTypeNode > node ) ;
2225
+ case SyntaxKind . TupleType :
2226
+ return getTypeFromTupleTypeNode ( < TupleTypeNode > node ) ;
2175
2227
case SyntaxKind . TypeLiteral :
2176
2228
return getTypeFromTypeLiteralNode ( < TypeLiteralNode > node ) ;
2177
2229
default :
@@ -2327,6 +2379,9 @@ module ts {
2327
2379
if ( type . flags & TypeFlags . Reference ) {
2328
2380
return createTypeReference ( ( < TypeReference > type ) . target , instantiateList ( ( < TypeReference > type ) . typeArguments , mapper , instantiateType ) ) ;
2329
2381
}
2382
+ if ( type . flags & TypeFlags . Tuple ) {
2383
+ return createTupleType ( instantiateList ( ( < TupleType > type ) . elementTypes , mapper , instantiateType ) ) ;
2384
+ }
2330
2385
}
2331
2386
return type ;
2332
2387
}
@@ -3015,20 +3070,16 @@ module ts {
3015
3070
while ( isArrayType ( type ) ) {
3016
3071
type = ( < GenericType > type ) . typeArguments [ 0 ] ;
3017
3072
}
3018
-
3019
3073
return type ;
3020
3074
}
3021
3075
3022
3076
function getWidenedTypeOfArrayLiteral ( type : Type ) : Type {
3023
3077
var elementType = ( < TypeReference > type ) . typeArguments [ 0 ] ;
3024
3078
var widenedType = getWidenedType ( elementType ) ;
3025
-
3026
3079
type = elementType !== widenedType ? createArrayType ( widenedType ) : type ;
3027
-
3028
3080
return type ;
3029
3081
}
3030
3082
3031
- /* If we are widening on a literal, then we may need to the 'node' parameter for reporting purposes */
3032
3083
function getWidenedType ( type : Type ) : Type {
3033
3084
if ( type . flags & ( TypeFlags . Undefined | TypeFlags . Null ) ) {
3034
3085
return anyType ;
@@ -3125,9 +3176,9 @@ module ts {
3125
3176
inferFromTypes ( sourceTypes [ i ] , targetTypes [ i ] ) ;
3126
3177
}
3127
3178
}
3128
- else if ( source . flags & TypeFlags . ObjectType && ( target . flags & TypeFlags . Reference || ( target . flags & TypeFlags . Anonymous ) &&
3129
- target . symbol && target . symbol . flags & ( SymbolFlags . Method | SymbolFlags . TypeLiteral ) ) ) {
3130
- // If source is an object type, and target is a type reference, the type of a method, or a type literal, infer from members
3179
+ else if ( source . flags & TypeFlags . ObjectType && ( target . flags & ( TypeFlags . Reference | TypeFlags . Tuple ) ||
3180
+ ( target . flags & TypeFlags . Anonymous ) && target . symbol && target . symbol . flags & ( SymbolFlags . Method | SymbolFlags . TypeLiteral ) ) ) {
3181
+ // If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members
3131
3182
if ( ! isInProcess ( source , target ) && isWithinDepthLimit ( source , sourceStack ) && isWithinDepthLimit ( target , targetStack ) ) {
3132
3183
if ( depth === 0 ) {
3133
3184
sourceStack = [ ] ;
@@ -3574,7 +3625,19 @@ module ts {
3574
3625
function getContextualTypeForElementExpression ( node : Expression ) : Type {
3575
3626
var arrayLiteral = < ArrayLiteral > node . parent ;
3576
3627
var type = getContextualType ( arrayLiteral ) ;
3577
- return type ? getIndexTypeOfType ( type , IndexKind . Number ) : undefined ;
3628
+ if ( type ) {
3629
+ if ( type . flags & TypeFlags . Tuple ) {
3630
+ var index = indexOf ( arrayLiteral . elements , node ) ;
3631
+ if ( index >= 0 ) {
3632
+ var prop = getPropertyOfType ( type , "" + index ) ;
3633
+ if ( prop ) {
3634
+ return getTypeOfSymbol ( prop ) ;
3635
+ }
3636
+ }
3637
+ }
3638
+ return getIndexTypeOfType ( type , IndexKind . Number ) ;
3639
+ }
3640
+ return undefined ;
3578
3641
}
3579
3642
3580
3643
function getContextualTypeForConditionalOperand ( node : Expression ) : Type {
@@ -3633,17 +3696,23 @@ module ts {
3633
3696
}
3634
3697
3635
3698
function checkArrayLiteral ( node : ArrayLiteral , contextualMapper ?: TypeMapper ) : Type {
3699
+ var contextualType = getContextualType ( node ) ;
3700
+ var isTupleLiteral = contextualType && ( contextualType . flags & TypeFlags . Tuple ) !== 0 ;
3636
3701
var elementTypes : Type [ ] = [ ] ;
3637
3702
forEach ( node . elements , element => {
3638
- if ( element . kind !== SyntaxKind . OmittedExpression ) {
3639
- var type = checkExpression ( element , contextualMapper ) ;
3640
- if ( ! contains ( elementTypes , type ) ) elementTypes . push ( type ) ;
3703
+ var type = element . kind !== SyntaxKind . OmittedExpression ? checkExpression ( element , contextualMapper ) : undefinedType ;
3704
+ if ( isTupleLiteral || ! contains ( elementTypes , type ) ) {
3705
+ elementTypes . push ( type ) ;
3641
3706
}
3642
3707
} ) ;
3643
- var contextualType = isInferentialContext ( contextualMapper ) ? undefined : getContextualType ( node ) ;
3644
- var contextualElementType = contextualType && getIndexTypeOfType ( contextualType , IndexKind . Number ) ;
3708
+ if ( isTupleLiteral ) {
3709
+ return createTupleType ( elementTypes ) ;
3710
+ }
3711
+ var contextualElementType = contextualType && ! isInferentialContext ( contextualMapper ) ? getIndexTypeOfType ( contextualType , IndexKind . Number ) : undefined ;
3645
3712
var elementType = getBestCommonType ( elementTypes , contextualElementType , true ) ;
3646
- if ( ! elementType ) elementType = elementTypes . length ? emptyObjectType : undefinedType ;
3713
+ if ( ! elementType ) {
3714
+ elementType = elementTypes . length ? emptyObjectType : undefinedType ;
3715
+ }
3647
3716
return createArrayType ( elementType ) ;
3648
3717
}
3649
3718
@@ -3711,11 +3780,11 @@ module ts {
3711
3780
}
3712
3781
3713
3782
function getDeclarationKindFromSymbol ( s : Symbol ) {
3714
- return s . flags & SymbolFlags . Prototype ? SyntaxKind . Property : s . valueDeclaration . kind ;
3783
+ return s . valueDeclaration ? s . valueDeclaration . kind : SyntaxKind . Property ;
3715
3784
}
3716
3785
3717
3786
function getDeclarationFlagsFromSymbol ( s : Symbol ) {
3718
- return s . flags & SymbolFlags . Prototype ? NodeFlags . Public | NodeFlags . Static : s . valueDeclaration . flags ;
3787
+ return s . valueDeclaration ? s . valueDeclaration . flags : s . flags & SymbolFlags . Prototype ? NodeFlags . Public | NodeFlags . Static : 0 ;
3719
3788
}
3720
3789
3721
3790
function checkPropertyAccess ( node : PropertyAccess ) {
@@ -4991,7 +5060,11 @@ module ts {
4991
5060
}
4992
5061
4993
5062
function checkArrayType ( node : ArrayTypeNode ) {
4994
- getTypeFromArrayTypeNode ( node ) ;
5063
+ checkSourceElement ( node . elementType ) ;
5064
+ }
5065
+
5066
+ function checkTupleType ( node : TupleTypeNode ) {
5067
+ forEach ( node . elementTypes , checkSourceElement ) ;
4995
5068
}
4996
5069
4997
5070
function isPrivateWithinAmbient ( node : Node ) : boolean {
@@ -6197,6 +6270,8 @@ module ts {
6197
6270
return checkTypeLiteral ( < TypeLiteralNode > node ) ;
6198
6271
case SyntaxKind . ArrayType :
6199
6272
return checkArrayType ( < ArrayTypeNode > node ) ;
6273
+ case SyntaxKind . TupleType :
6274
+ return checkTupleType ( < TupleTypeNode > node ) ;
6200
6275
case SyntaxKind . FunctionDeclaration :
6201
6276
return checkFunctionDeclaration ( < FunctionDeclaration > node ) ;
6202
6277
case SyntaxKind . Block :
0 commit comments