@@ -56,6 +56,7 @@ module ts {
5656 var globalBooleanType : ObjectType ;
5757 var globalRegExpType : ObjectType ;
5858
59+ var tupleTypes : Map < TupleType > = { } ;
5960 var stringLiteralTypes : Map < StringLiteralType > = { } ;
6061
6162 var fullTypeCheck = false ;
@@ -619,15 +620,13 @@ module ts {
619620 }
620621
621622 function isOptionalProperty ( propertySymbol : Symbol ) : boolean {
622- if ( propertySymbol . flags & SymbolFlags . Prototype ) {
623- return false ;
624- }
625623 // class C {
626624 // constructor(public x?) { }
627625 // }
628626 //
629627 // 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 ;
631630 }
632631
633632 function forEachSymbolTableInScope < T > ( enclosingDeclaration : Node , callback : ( symbolTable : SymbolTable ) => T ) : T {
@@ -843,6 +842,9 @@ module ts {
843842 else if ( type . flags & ( TypeFlags . Class | TypeFlags . Interface | TypeFlags . Enum | TypeFlags . TypeParameter ) ) {
844843 writer . writeSymbol ( type . symbol , enclosingDeclaration , SymbolFlags . Type ) ;
845844 }
845+ else if ( type . flags & TypeFlags . Tuple ) {
846+ writeTupleType ( < TupleType > type ) ;
847+ }
846848 else if ( type . flags & TypeFlags . Anonymous ) {
847849 writeAnonymousType ( < ObjectType > type , allowFunctionOrConstructorTypeLiteral ) ;
848850 }
@@ -855,6 +857,15 @@ module ts {
855857 }
856858 }
857859
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+
858869 function writeTypeReference ( type : TypeReference ) {
859870 if ( type . target === globalArrayType && ! ( flags & TypeFormatFlags . WriteArrayAsGenericType ) ) {
860871 // If we are writing array element type the arrow style signatures are not allowed as
@@ -865,16 +876,17 @@ module ts {
865876 else {
866877 writer . writeSymbol ( type . target . symbol , enclosingDeclaration , SymbolFlags . Type ) ;
867878 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 ) ;
874880 writer . write ( ">" ) ;
875881 }
876882 }
877883
884+ function writeTupleType ( type : TupleType ) {
885+ writer . write ( "[" ) ;
886+ writeTypeList ( type . elementTypes ) ;
887+ writer . write ( "]" ) ;
888+ }
889+
878890 function writeAnonymousType ( type : ObjectType , allowFunctionOrConstructorTypeLiteral : boolean ) {
879891 // Always use 'typeof T' for type of class, enum, and module objects
880892 if ( type . symbol && type . symbol . flags & ( SymbolFlags . Class | SymbolFlags . Enum | SymbolFlags . ValueModule ) ) {
@@ -1649,6 +1661,23 @@ module ts {
16491661 return [ createSignature ( undefined , classType . typeParameters , emptyArray , classType , 0 , false , false ) ] ;
16501662 }
16511663
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+
16521681 function resolveAnonymousTypeMembers ( type : ObjectType ) {
16531682 var symbol = type . symbol ;
16541683 var members = emptySymbols ;
@@ -1682,6 +1711,9 @@ module ts {
16821711 else if ( type . flags & TypeFlags . Anonymous ) {
16831712 resolveAnonymousTypeMembers ( < ObjectType > type ) ;
16841713 }
1714+ else if ( type . flags & TypeFlags . Tuple ) {
1715+ resolveTupleTypeMembers ( < TupleType > type ) ;
1716+ }
16851717 else {
16861718 resolveTypeReferenceMembers ( < TypeReference > type ) ;
16871719 }
@@ -2123,6 +2155,24 @@ module ts {
21232155 return links . resolvedType ;
21242156 }
21252157
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+
21262176 function getTypeFromTypeLiteralNode ( node : TypeLiteralNode ) : Type {
21272177 var links = getNodeLinks ( node ) ;
21282178 if ( ! links . resolvedType ) {
@@ -2172,6 +2222,8 @@ module ts {
21722222 return getTypeFromTypeQueryNode ( < TypeQueryNode > node ) ;
21732223 case SyntaxKind . ArrayType :
21742224 return getTypeFromArrayTypeNode ( < ArrayTypeNode > node ) ;
2225+ case SyntaxKind . TupleType :
2226+ return getTypeFromTupleTypeNode ( < TupleTypeNode > node ) ;
21752227 case SyntaxKind . TypeLiteral :
21762228 return getTypeFromTypeLiteralNode ( < TypeLiteralNode > node ) ;
21772229 default :
@@ -2327,6 +2379,9 @@ module ts {
23272379 if ( type . flags & TypeFlags . Reference ) {
23282380 return createTypeReference ( ( < TypeReference > type ) . target , instantiateList ( ( < TypeReference > type ) . typeArguments , mapper , instantiateType ) ) ;
23292381 }
2382+ if ( type . flags & TypeFlags . Tuple ) {
2383+ return createTupleType ( instantiateList ( ( < TupleType > type ) . elementTypes , mapper , instantiateType ) ) ;
2384+ }
23302385 }
23312386 return type ;
23322387 }
@@ -3015,20 +3070,16 @@ module ts {
30153070 while ( isArrayType ( type ) ) {
30163071 type = ( < GenericType > type ) . typeArguments [ 0 ] ;
30173072 }
3018-
30193073 return type ;
30203074 }
30213075
30223076 function getWidenedTypeOfArrayLiteral ( type : Type ) : Type {
30233077 var elementType = ( < TypeReference > type ) . typeArguments [ 0 ] ;
30243078 var widenedType = getWidenedType ( elementType ) ;
3025-
30263079 type = elementType !== widenedType ? createArrayType ( widenedType ) : type ;
3027-
30283080 return type ;
30293081 }
30303082
3031- /* If we are widening on a literal, then we may need to the 'node' parameter for reporting purposes */
30323083 function getWidenedType ( type : Type ) : Type {
30333084 if ( type . flags & ( TypeFlags . Undefined | TypeFlags . Null ) ) {
30343085 return anyType ;
@@ -3125,9 +3176,9 @@ module ts {
31253176 inferFromTypes ( sourceTypes [ i ] , targetTypes [ i ] ) ;
31263177 }
31273178 }
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
31313182 if ( ! isInProcess ( source , target ) && isWithinDepthLimit ( source , sourceStack ) && isWithinDepthLimit ( target , targetStack ) ) {
31323183 if ( depth === 0 ) {
31333184 sourceStack = [ ] ;
@@ -3574,7 +3625,19 @@ module ts {
35743625 function getContextualTypeForElementExpression ( node : Expression ) : Type {
35753626 var arrayLiteral = < ArrayLiteral > node . parent ;
35763627 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 ;
35783641 }
35793642
35803643 function getContextualTypeForConditionalOperand ( node : Expression ) : Type {
@@ -3633,17 +3696,23 @@ module ts {
36333696 }
36343697
36353698 function checkArrayLiteral ( node : ArrayLiteral , contextualMapper ?: TypeMapper ) : Type {
3699+ var contextualType = getContextualType ( node ) ;
3700+ var isTupleLiteral = contextualType && ( contextualType . flags & TypeFlags . Tuple ) !== 0 ;
36363701 var elementTypes : Type [ ] = [ ] ;
36373702 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 ) ;
36413706 }
36423707 } ) ;
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 ;
36453712 var elementType = getBestCommonType ( elementTypes , contextualElementType , true ) ;
3646- if ( ! elementType ) elementType = elementTypes . length ? emptyObjectType : undefinedType ;
3713+ if ( ! elementType ) {
3714+ elementType = elementTypes . length ? emptyObjectType : undefinedType ;
3715+ }
36473716 return createArrayType ( elementType ) ;
36483717 }
36493718
@@ -3711,11 +3780,11 @@ module ts {
37113780 }
37123781
37133782 function getDeclarationKindFromSymbol ( s : Symbol ) {
3714- return s . flags & SymbolFlags . Prototype ? SyntaxKind . Property : s . valueDeclaration . kind ;
3783+ return s . valueDeclaration ? s . valueDeclaration . kind : SyntaxKind . Property ;
37153784 }
37163785
37173786 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 ;
37193788 }
37203789
37213790 function checkPropertyAccess ( node : PropertyAccess ) {
@@ -4991,7 +5060,11 @@ module ts {
49915060 }
49925061
49935062 function checkArrayType ( node : ArrayTypeNode ) {
4994- getTypeFromArrayTypeNode ( node ) ;
5063+ checkSourceElement ( node . elementType ) ;
5064+ }
5065+
5066+ function checkTupleType ( node : TupleTypeNode ) {
5067+ forEach ( node . elementTypes , checkSourceElement ) ;
49955068 }
49965069
49975070 function isPrivateWithinAmbient ( node : Node ) : boolean {
@@ -6197,6 +6270,8 @@ module ts {
61976270 return checkTypeLiteral ( < TypeLiteralNode > node ) ;
61986271 case SyntaxKind . ArrayType :
61996272 return checkArrayType ( < ArrayTypeNode > node ) ;
6273+ case SyntaxKind . TupleType :
6274+ return checkTupleType ( < TupleTypeNode > node ) ;
62006275 case SyntaxKind . FunctionDeclaration :
62016276 return checkFunctionDeclaration ( < FunctionDeclaration > node ) ;
62026277 case SyntaxKind . Block :
0 commit comments