@@ -3400,9 +3400,12 @@ namespace ts {
34003400 if (typeArguments.length > 0) {
34013401 const arity = getTypeReferenceArity(type);
34023402 const tupleConstituentNodes = mapToTypeNodes(typeArguments.slice(0, arity), context);
3403+ const hasRestElement = (<TupleType>type.target).hasRestElement;
34033404 if (tupleConstituentNodes && tupleConstituentNodes.length > 0) {
34043405 for (let i = (<TupleType>type.target).minLength; i < arity; i++) {
3405- tupleConstituentNodes[i] = createOptionalTypeNode(tupleConstituentNodes[i]);
3406+ tupleConstituentNodes[i] = hasRestElement && i === arity - 1 ?
3407+ createRestTypeNode(createArrayTypeNode(tupleConstituentNodes[i])) :
3408+ createOptionalTypeNode(tupleConstituentNodes[i]);
34063409 }
34073410 return createTupleTypeNode(tupleConstituentNodes);
34083411 }
@@ -4842,7 +4845,7 @@ namespace ts {
48424845 }
48434846 // If the pattern has at least one element, and no rest element, then it should imply a tuple type.
48444847 const elementTypes = map(elements, e => isOmittedExpression(e) ? anyType : getTypeFromBindingElement(e, includePatternInType, reportErrors));
4845- let result = createTupleType(elementTypes);
4848+ let result = <TypeReference> createTupleType(elementTypes);
48464849 if (includePatternInType) {
48474850 result = cloneTypeReference(result);
48484851 result.pattern = pattern;
@@ -8282,21 +8285,25 @@ namespace ts {
82828285 //
82838286 // Note that the generic type created by this function has no symbol associated with it. The same
82848287 // is true for each of the synthesized type parameters.
8285- function createTupleTypeOfArity(arity: number, minLength: number, associatedNames: __String[] | undefined): TupleType {
8288+ function createTupleTypeOfArity(arity: number, minLength: number, hasRestElement: boolean, associatedNames: __String[] | undefined): TupleType {
82868289 let typeParameters: TypeParameter[] | undefined;
82878290 const properties: Symbol[] = [];
8291+ const maxLength = hasRestElement ? arity - 1 : arity;
82888292 if (arity) {
82898293 typeParameters = new Array(arity);
82908294 for (let i = 0; i < arity; i++) {
8291- const property = createSymbol(SymbolFlags.Property | (i >= minLength ? SymbolFlags.Optional : 0), "" + i as __String);
8292- property.type = typeParameters[i] = <TypeParameter>createType(TypeFlags.TypeParameter);
8293- properties.push(property);
8295+ const typeParameter = typeParameters[i] = <TypeParameter>createType(TypeFlags.TypeParameter);
8296+ if (i < maxLength) {
8297+ const property = createSymbol(SymbolFlags.Property | (i >= minLength ? SymbolFlags.Optional : 0), "" + i as __String);
8298+ property.type = typeParameter;
8299+ properties.push(property);
8300+ }
82948301 }
82958302 }
82968303 const literalTypes = [];
8297- for (let i = minLength; i <= arity ; i++) literalTypes.push(getLiteralType(i));
8304+ for (let i = minLength; i <= maxLength ; i++) literalTypes.push(getLiteralType(i));
82988305 const lengthSymbol = createSymbol(SymbolFlags.Property, "length" as __String);
8299- lengthSymbol.type = getUnionType(literalTypes);
8306+ lengthSymbol.type = hasRestElement ? numberType : getUnionType(literalTypes);
83008307 properties.push(lengthSymbol);
83018308 const type = <TupleType & InterfaceTypeWithDeclaredMembers>createObjectType(ObjectFlags.Tuple | ObjectFlags.Reference);
83028309 type.typeParameters = typeParameters;
@@ -8315,29 +8322,40 @@ namespace ts {
83158322 type.declaredStringIndexInfo = undefined;
83168323 type.declaredNumberIndexInfo = undefined;
83178324 type.minLength = minLength;
8325+ type.hasRestElement = hasRestElement;
83188326 type.associatedNames = associatedNames;
83198327 return type;
83208328 }
83218329
8322- function getTupleTypeOfArity(arity: number, minLength: number, associatedNames?: __String[]): GenericType {
8323- const key = arity + "," + minLength + (associatedNames && associatedNames.length ? "," + associatedNames.join(",") : "");
8330+ function getTupleTypeOfArity(arity: number, minLength: number, hasRestElement: boolean, associatedNames?: __String[]): GenericType {
8331+ const key = arity + (hasRestElement ? "+" : ",") + minLength + (associatedNames && associatedNames.length ? "," + associatedNames.join(",") : "");
83248332 let type = tupleTypes.get(key);
83258333 if (!type) {
8326- tupleTypes.set(key, type = createTupleTypeOfArity(arity, minLength, associatedNames));
8334+ tupleTypes.set(key, type = createTupleTypeOfArity(arity, minLength, hasRestElement, associatedNames));
83278335 }
83288336 return type;
83298337 }
83308338
8331- function createTupleType(elementTypes: Type[], minLength = elementTypes.length, associatedNames?: __String[]) {
8332- const tupleType = getTupleTypeOfArity(elementTypes.length, minLength, associatedNames);
8339+ function createTupleType(elementTypes: Type[], minLength = elementTypes.length, hasRestElement = false, associatedNames?: __String[]) {
8340+ const arity = elementTypes.length;
8341+ if (arity === 1 && hasRestElement) {
8342+ return createArrayType(elementTypes[0]);
8343+ }
8344+ const tupleType = getTupleTypeOfArity(arity, minLength, arity > 0 && hasRestElement, associatedNames);
83338345 return elementTypes.length ? createTypeReference(tupleType, elementTypes) : tupleType;
83348346 }
83358347
83368348 function getTypeFromTupleTypeNode(node: TupleTypeNode): Type {
83378349 const links = getNodeLinks(node);
83388350 if (!links.resolvedType) {
8339- const minLength = findLastIndex(node.elementTypes, n => n.kind !== SyntaxKind.OptionalType) + 1;
8340- links.resolvedType = createTupleType(map(node.elementTypes, getTypeFromTypeNode), minLength);
8351+ const lastElement = lastOrUndefined(node.elementTypes);
8352+ const restElement = lastElement && lastElement.kind === SyntaxKind.RestType ? lastElement : undefined;
8353+ const minLength = findLastIndex(node.elementTypes, n => n.kind !== SyntaxKind.OptionalType && n !== restElement) + 1;
8354+ const elementTypes = map(node.elementTypes, n => {
8355+ const type = getTypeFromTypeNode(n);
8356+ return n === restElement ? getIndexTypeOfType(type, IndexKind.Number) || errorType : type;
8357+ });
8358+ links.resolvedType = createTupleType(elementTypes, minLength, !!restElement);
83418359 }
83428360 return links.resolvedType;
83438361 }
@@ -9548,9 +9566,10 @@ namespace ts {
95489566 case SyntaxKind.JSDocOptionalType:
95499567 return addOptionality(getTypeFromTypeNode((node as JSDocOptionalType).type));
95509568 case SyntaxKind.ParenthesizedType:
9569+ case SyntaxKind.RestType:
95519570 case SyntaxKind.JSDocNonNullableType:
95529571 case SyntaxKind.JSDocTypeExpression:
9553- return getTypeFromTypeNode((<ParenthesizedTypeNode | JSDocTypeReferencingNode | JSDocTypeExpression>node).type);
9572+ return getTypeFromTypeNode((<ParenthesizedTypeNode | RestTypeNode | JSDocTypeReferencingNode | JSDocTypeExpression>node).type);
95549573 case SyntaxKind.JSDocVariadicType:
95559574 return getTypeFromJSDocVariadicType(node as JSDocVariadicType);
95569575 case SyntaxKind.FunctionType:
@@ -11346,6 +11365,35 @@ namespace ts {
1134611365 }
1134711366 }
1134811367 }
11368+ if (isTupleType(target)) {
11369+ const targetRestType = getRestTypeOfTupleType(<TypeReference>target);
11370+ if (targetRestType) {
11371+ if (!isTupleType(source)) {
11372+ return Ternary.False;
11373+ }
11374+ const sourceRestType = getRestTypeOfTupleType(<TypeReference>source);
11375+ if (sourceRestType && !isRelatedTo(sourceRestType, targetRestType, reportErrors)) {
11376+ if (reportErrors) {
11377+ // !!! Rest element types are incompatible
11378+ reportError(Diagnostics.Index_signatures_are_incompatible);
11379+ }
11380+ return Ternary.False;
11381+ }
11382+ const targetCount = getTypeReferenceArity(<TypeReference>target) - 1;
11383+ const sourceCount = getTypeReferenceArity(<TypeReference>source) - (sourceRestType ? 1 : 0);
11384+ for (let i = targetCount; i < sourceCount; i++) {
11385+ const related = isRelatedTo((<TypeReference>source).typeArguments![i], targetRestType, reportErrors);
11386+ if (!related) {
11387+ if (reportErrors) {
11388+ // !!! Property {0} is incompatible with rest element type
11389+ reportError(Diagnostics.Property_0_is_incompatible_with_index_signature, "" + i);
11390+ }
11391+ return Ternary.False;
11392+ }
11393+ result &= related;
11394+ }
11395+ }
11396+ }
1134911397 return result;
1135011398 }
1135111399
@@ -12028,6 +12076,10 @@ namespace ts {
1202812076 return !!(getObjectFlags(type) & ObjectFlags.Reference && (<TypeReference>type).target.objectFlags & ObjectFlags.Tuple);
1202912077 }
1203012078
12079+ function getRestTypeOfTupleType(type: TypeReference) {
12080+ return (<TupleType>type.target).hasRestElement ? type.typeArguments![type.target.typeParameters!.length - 1] : undefined;
12081+ }
12082+
1203112083 function getFalsyFlagsOfTypes(types: Type[]): TypeFlags {
1203212084 let result: TypeFlags = 0;
1203312085 for (const t of types) {
@@ -12400,7 +12452,7 @@ namespace ts {
1240012452 }
1240112453 const minArgumentCount = getMinArgumentCount(source);
1240212454 const minLength = minArgumentCount < paramCount ? 0 : minArgumentCount - paramCount;
12403- const rest = sourceHasRest ? createArrayType(getUnionType(types)) : createTupleType(types, minLength, names);
12455+ const rest = sourceHasRest ? createArrayType(getUnionType(types)) : createTupleType(types, minLength, /*hasRestElement*/ false, names);
1240412456 callback(rest, targetRestTypeVariable);
1240512457 }
1240612458 }
@@ -15899,7 +15951,7 @@ namespace ts {
1589915951 // If array literal is actually a destructuring pattern, mark it as an implied type. We do this such
1590015952 // that we get the same behavior for "var [x, y] = []" and "[x, y] = []".
1590115953 if (inDestructuringPattern && elementTypes.length) {
15902- const type = cloneTypeReference(createTupleType(elementTypes));
15954+ const type = cloneTypeReference(<TypeReference> createTupleType(elementTypes));
1590315955 type.pattern = node;
1590415956 return type;
1590515957 }
@@ -25639,6 +25691,7 @@ namespace ts {
2563925691 return checkUnionOrIntersectionType(<UnionOrIntersectionTypeNode>node);
2564025692 case SyntaxKind.ParenthesizedType:
2564125693 case SyntaxKind.OptionalType:
25694+ case SyntaxKind.RestType:
2564225695 return checkSourceElement((<ParenthesizedTypeNode | OptionalTypeNode>node).type);
2564325696 case SyntaxKind.TypeOperator:
2564425697 return checkTypeOperator(<TypeOperatorNode>node);
0 commit comments