@@ -4568,9 +4568,9 @@ namespace ts {
45684568 createRestTypeNode(createArrayTypeNode(tupleConstituentNodes[i])) :
45694569 createOptionalTypeNode(tupleConstituentNodes[i]);
45704570 }
4571- if ((type.target as TupleType).associatedNames ) {
4571+ if ((type.target as TupleType).labeledElementDeclarations ) {
45724572 for (let i = 0; i < tupleConstituentNodes.length; i++) {
4573- tupleConstituentNodes[i] = createNamedTupleMember(createIdentifier(unescapeLeadingUnderscores(( type.target as TupleType).associatedNames ![i])), tupleConstituentNodes[i]);
4573+ tupleConstituentNodes[i] = createNamedTupleMember(createIdentifier(unescapeLeadingUnderscores(getTupleElementLabel(( type.target as TupleType).labeledElementDeclarations ![i]) )), tupleConstituentNodes[i]);
45744574 }
45754575 }
45764576 const tupleTypeNode = setEmitFlags(createTupleTypeNode(tupleConstituentNodes), EmitFlags.SingleLine);
@@ -12082,15 +12082,8 @@ namespace ts {
1208212082 const lastElement = lastOrUndefined(node.elements);
1208312083 const restElement = lastElement && unwrapNamedTupleMember(lastElement).kind === SyntaxKind.RestType ? lastElement : undefined;
1208412084 const minLength = findLastIndex(node.elements, n => unwrapNamedTupleMember(n).kind !== SyntaxKind.OptionalType && n !== restElement) + 1;
12085- let missingName = false;
12086- const names = map(node.elements, e => {
12087- if (e.kind !== SyntaxKind.NamedTupleMember) {
12088- missingName = true;
12089- return escapeLeadingUnderscores("arg");
12090- }
12091- return (e as NamedTupleMember).name.escapedText;
12092- });
12093- return getTupleTypeOfArity(node.elements.length, minLength, !!restElement, readonly, /*associatedNames*/ missingName ? undefined : names);
12085+ const missingName = some(node.elements, e => e.kind !== SyntaxKind.NamedTupleMember);
12086+ return getTupleTypeOfArity(node.elements.length, minLength, !!restElement, readonly, /*associatedNames*/ missingName ? undefined : node.elements as readonly NamedTupleMember[]);
1209412087 }
1209512088
1209612089 // Return true if the given type reference node is directly aliased or if it needs to be deferred
@@ -12187,7 +12180,7 @@ namespace ts {
1218712180 //
1218812181 // Note that the generic type created by this function has no symbol associated with it. The same
1218912182 // is true for each of the synthesized type parameters.
12190- function createTupleTypeOfArity(arity: number, minLength: number, hasRestElement: boolean, readonly: boolean, associatedNames: __String [] | undefined): TupleType {
12183+ function createTupleTypeOfArity(arity: number, minLength: number, hasRestElement: boolean, readonly: boolean, namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration) [] | undefined): TupleType {
1219112184 let typeParameters: TypeParameter[] | undefined;
1219212185 const properties: Symbol[] = [];
1219312186 const maxLength = hasRestElement ? arity - 1 : arity;
@@ -12198,6 +12191,7 @@ namespace ts {
1219812191 if (i < maxLength) {
1219912192 const property = createSymbol(SymbolFlags.Property | (i >= minLength ? SymbolFlags.Optional : 0),
1220012193 "" + i as __String, readonly ? CheckFlags.Readonly : 0);
12194+ property.tupleLabelDeclaration = namedMemberDeclarations?.[i];
1220112195 property.type = typeParameter;
1220212196 properties.push(property);
1220312197 }
@@ -12227,25 +12221,25 @@ namespace ts {
1222712221 type.minLength = minLength;
1222812222 type.hasRestElement = hasRestElement;
1222912223 type.readonly = readonly;
12230- type.associatedNames = associatedNames ;
12224+ type.labeledElementDeclarations = namedMemberDeclarations ;
1223112225 return type;
1223212226 }
1223312227
12234- function getTupleTypeOfArity(arity: number, minLength: number, hasRestElement: boolean, readonly: boolean, associatedNames ?: __String []): GenericType {
12235- const key = arity + (hasRestElement ? "+" : ",") + minLength + (readonly ? "R" : "") + (associatedNames && associatedNames .length ? "," + associatedNames .join(",") : "");
12228+ function getTupleTypeOfArity(arity: number, minLength: number, hasRestElement: boolean, readonly: boolean, namedMemberDeclarations ?: readonly (NamedTupleMember | ParameterDeclaration) []): GenericType {
12229+ const key = arity + (hasRestElement ? "+" : ",") + minLength + (readonly ? "R" : "") + (namedMemberDeclarations && namedMemberDeclarations .length ? "," + map(namedMemberDeclarations, getNodeId) .join(",") : "");
1223612230 let type = tupleTypes.get(key);
1223712231 if (!type) {
12238- tupleTypes.set(key, type = createTupleTypeOfArity(arity, minLength, hasRestElement, readonly, associatedNames ));
12232+ tupleTypes.set(key, type = createTupleTypeOfArity(arity, minLength, hasRestElement, readonly, namedMemberDeclarations ));
1223912233 }
1224012234 return type;
1224112235 }
1224212236
12243- function createTupleType(elementTypes: readonly Type[], minLength = elementTypes.length, hasRestElement = false, readonly = false, associatedNames ?: __String []) {
12237+ function createTupleType(elementTypes: readonly Type[], minLength = elementTypes.length, hasRestElement = false, readonly = false, namedMemberDeclarations ?: readonly (NamedTupleMember | ParameterDeclaration) []) {
1224412238 const arity = elementTypes.length;
1224512239 if (arity === 1 && hasRestElement) {
1224612240 return createArrayType(elementTypes[0], readonly);
1224712241 }
12248- const tupleType = getTupleTypeOfArity(arity, minLength, arity > 0 && hasRestElement, readonly, associatedNames );
12242+ const tupleType = getTupleTypeOfArity(arity, minLength, arity > 0 && hasRestElement, readonly, namedMemberDeclarations );
1224912243 return elementTypes.length ? createTypeReference(tupleType, elementTypes) : tupleType;
1225012244 }
1225112245
@@ -12260,7 +12254,7 @@ namespace ts {
1226012254 Math.max(0, tuple.minLength - index),
1226112255 tuple.hasRestElement,
1226212256 tuple.readonly,
12263- tuple.associatedNames && tuple.associatedNames .slice(index),
12257+ tuple.labeledElementDeclarations && tuple.labeledElementDeclarations .slice(index),
1226412258 );
1226512259 }
1226612260
@@ -14260,7 +14254,7 @@ namespace ts {
1426014254 minLength;
1426114255 const newReadonly = getModifiedReadonlyState(tupleType.target.readonly, modifiers);
1426214256 return contains(elementTypes, errorType) ? errorType :
14263- createTupleType(elementTypes, newMinLength, tupleType.target.hasRestElement, newReadonly, tupleType.target.associatedNames );
14257+ createTupleType(elementTypes, newMinLength, tupleType.target.hasRestElement, newReadonly, tupleType.target.labeledElementDeclarations );
1426414258 }
1426514259
1426614260 function instantiateMappedTypeTemplate(type: MappedType, key: Type, isOptional: boolean, mapper: TypeMapper) {
@@ -18517,7 +18511,7 @@ namespace ts {
1851718511 const elementTypes = map(getTypeArguments(source), t => inferReverseMappedType(t, target, constraint));
1851818512 const minLength = getMappedTypeModifiers(target) & MappedTypeModifiers.IncludeOptional ?
1851918513 getTypeReferenceArity(source) - (source.target.hasRestElement ? 1 : 0) : source.target.minLength;
18520- return createTupleType(elementTypes, minLength, source.target.hasRestElement, source.target.readonly, source.target.associatedNames );
18514+ return createTupleType(elementTypes, minLength, source.target.hasRestElement, source.target.readonly, source.target.labeledElementDeclarations );
1852118515 }
1852218516 // For all other object types we infer a new object type where the reverse mapping has been
1852318517 // applied to the type of each property.
@@ -25114,7 +25108,7 @@ namespace ts {
2511425108 function getArrayifiedType(type: Type) {
2511525109 return type.flags & TypeFlags.Union ? mapType(type, getArrayifiedType) :
2511625110 type.flags & (TypeFlags.Any | TypeFlags.Instantiable) || isMutableArrayOrTuple(type) ? type :
25117- isTupleType(type) ? createTupleType(getTypeArguments(type), type.target.minLength, type.target.hasRestElement, /*readonly*/ false, type.target.associatedNames ) :
25111+ isTupleType(type) ? createTupleType(getTypeArguments(type), type.target.minLength, type.target.hasRestElement, /*readonly*/ false, type.target.labeledElementDeclarations ) :
2511825112 createArrayType(getIndexedAccessType(type, numberType));
2511925113 }
2512025114
@@ -26974,6 +26968,11 @@ namespace ts {
2697426968 return type;
2697526969 }
2697626970
26971+ function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember) {
26972+ Debug.assert(isIdentifier(d.name)); // Parameter declarations could be binding patterns, but we only allow identifier names
26973+ return d.name.escapedText;
26974+ }
26975+
2697726976 function getParameterNameAtPosition(signature: Signature, pos: number) {
2697826977 const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
2697926978 if (pos < paramCount) {
@@ -26982,13 +26981,33 @@ namespace ts {
2698226981 const restParameter = signature.parameters[paramCount] || unknownSymbol;
2698326982 const restType = getTypeOfSymbol(restParameter);
2698426983 if (isTupleType(restType)) {
26985- const associatedNames = (<TupleType>(<TypeReference>restType).target).associatedNames ;
26984+ const associatedNames = (<TupleType>(<TypeReference>restType).target).labeledElementDeclarations ;
2698626985 const index = pos - paramCount;
26987- return associatedNames && associatedNames[index] || restParameter.escapedName + "_" + index as __String;
26986+ return associatedNames && getTupleElementLabel( associatedNames[index]) || restParameter.escapedName + "_" + index as __String;
2698826987 }
2698926988 return restParameter.escapedName;
2699026989 }
2699126990
26991+ function isValidDeclarationForTupleLabel(d: Declaration): d is NamedTupleMember | (ParameterDeclaration & { name: Identifier }) {
26992+ return d.kind === SyntaxKind.NamedTupleMember || (isParameter(d) && isIdentifier(d.name));
26993+ }
26994+
26995+ function getNameableDeclarationAtPosition(signature: Signature, pos: number) {
26996+ const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
26997+ if (pos < paramCount) {
26998+ const decl = signature.parameters[pos].valueDeclaration;
26999+ return decl && isValidDeclarationForTupleLabel(decl) ? decl : undefined;
27000+ }
27001+ const restParameter = signature.parameters[paramCount] || unknownSymbol;
27002+ const restType = getTypeOfSymbol(restParameter);
27003+ if (isTupleType(restType)) {
27004+ const associatedNames = (<TupleType>(<TypeReference>restType).target).labeledElementDeclarations;
27005+ const index = pos - paramCount;
27006+ return associatedNames && associatedNames[index];
27007+ }
27008+ return restParameter.valueDeclaration && isValidDeclarationForTupleLabel(restParameter.valueDeclaration) ? restParameter.valueDeclaration : undefined;
27009+ }
27010+
2699227011 function getTypeAtPosition(signature: Signature, pos: number): Type {
2699327012 return tryGetTypeAtPosition(signature, pos) || anyType;
2699427013 }
@@ -27019,14 +27038,26 @@ namespace ts {
2701927038 return restType;
2702027039 }
2702127040 const types = [];
27022- const names = [];
27041+ let names: (NamedTupleMember | ParameterDeclaration)[] | undefined = [];
2702327042 for (let i = pos; i < nonRestCount; i++) {
2702427043 types.push(getTypeAtPosition(source, i));
27025- names.push(getParameterNameAtPosition(source, i));
27044+ const name = getNameableDeclarationAtPosition(source, i);
27045+ if (name && names) {
27046+ names.push(name);
27047+ }
27048+ else {
27049+ names = undefined;
27050+ }
2702627051 }
2702727052 if (restType) {
2702827053 types.push(getIndexedAccessType(restType, numberType));
27029- names.push(getParameterNameAtPosition(source, nonRestCount));
27054+ const name = getNameableDeclarationAtPosition(source, nonRestCount);
27055+ if (name && names) {
27056+ names.push(name);
27057+ }
27058+ else {
27059+ names = undefined;
27060+ }
2703027061 }
2703127062 const minArgumentCount = getMinArgumentCount(source);
2703227063 const minLength = minArgumentCount < pos ? 0 : minArgumentCount - pos;
0 commit comments