@@ -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);
@@ -12104,15 +12104,8 @@ namespace ts {
1210412104 const lastElement = lastOrUndefined(node.elements);
1210512105 const restElement = lastElement && unwrapNamedTupleMember(lastElement).kind === SyntaxKind.RestType ? lastElement : undefined;
1210612106 const minLength = findLastIndex(node.elements, n => unwrapNamedTupleMember(n).kind !== SyntaxKind.OptionalType && n !== restElement) + 1;
12107- let missingName = false;
12108- const names = map(node.elements, e => {
12109- if (e.kind !== SyntaxKind.NamedTupleMember) {
12110- missingName = true;
12111- return escapeLeadingUnderscores("arg");
12112- }
12113- return (e as NamedTupleMember).name.escapedText;
12114- });
12115- return getTupleTypeOfArity(node.elements.length, minLength, !!restElement, readonly, /*associatedNames*/ missingName ? undefined : names);
12107+ const missingName = some(node.elements, e => e.kind !== SyntaxKind.NamedTupleMember);
12108+ return getTupleTypeOfArity(node.elements.length, minLength, !!restElement, readonly, /*associatedNames*/ missingName ? undefined : node.elements as readonly NamedTupleMember[]);
1211612109 }
1211712110
1211812111 // Return true if the given type reference node is directly aliased or if it needs to be deferred
@@ -12209,7 +12202,7 @@ namespace ts {
1220912202 //
1221012203 // Note that the generic type created by this function has no symbol associated with it. The same
1221112204 // is true for each of the synthesized type parameters.
12212- function createTupleTypeOfArity(arity: number, minLength: number, hasRestElement: boolean, readonly: boolean, associatedNames: __String [] | undefined): TupleType {
12205+ function createTupleTypeOfArity(arity: number, minLength: number, hasRestElement: boolean, readonly: boolean, namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration) [] | undefined): TupleType {
1221312206 let typeParameters: TypeParameter[] | undefined;
1221412207 const properties: Symbol[] = [];
1221512208 const maxLength = hasRestElement ? arity - 1 : arity;
@@ -12220,6 +12213,7 @@ namespace ts {
1222012213 if (i < maxLength) {
1222112214 const property = createSymbol(SymbolFlags.Property | (i >= minLength ? SymbolFlags.Optional : 0),
1222212215 "" + i as __String, readonly ? CheckFlags.Readonly : 0);
12216+ property.tupleLabelDeclaration = namedMemberDeclarations?.[i];
1222312217 property.type = typeParameter;
1222412218 properties.push(property);
1222512219 }
@@ -12249,25 +12243,25 @@ namespace ts {
1224912243 type.minLength = minLength;
1225012244 type.hasRestElement = hasRestElement;
1225112245 type.readonly = readonly;
12252- type.associatedNames = associatedNames ;
12246+ type.labeledElementDeclarations = namedMemberDeclarations ;
1225312247 return type;
1225412248 }
1225512249
12256- function getTupleTypeOfArity(arity: number, minLength: number, hasRestElement: boolean, readonly: boolean, associatedNames ?: __String []): GenericType {
12257- const key = arity + (hasRestElement ? "+" : ",") + minLength + (readonly ? "R" : "") + (associatedNames && associatedNames .length ? "," + associatedNames .join(",") : "");
12250+ function getTupleTypeOfArity(arity: number, minLength: number, hasRestElement: boolean, readonly: boolean, namedMemberDeclarations ?: readonly (NamedTupleMember | ParameterDeclaration) []): GenericType {
12251+ const key = arity + (hasRestElement ? "+" : ",") + minLength + (readonly ? "R" : "") + (namedMemberDeclarations && namedMemberDeclarations .length ? "," + map(namedMemberDeclarations, getNodeId) .join(",") : "");
1225812252 let type = tupleTypes.get(key);
1225912253 if (!type) {
12260- tupleTypes.set(key, type = createTupleTypeOfArity(arity, minLength, hasRestElement, readonly, associatedNames ));
12254+ tupleTypes.set(key, type = createTupleTypeOfArity(arity, minLength, hasRestElement, readonly, namedMemberDeclarations ));
1226112255 }
1226212256 return type;
1226312257 }
1226412258
12265- function createTupleType(elementTypes: readonly Type[], minLength = elementTypes.length, hasRestElement = false, readonly = false, associatedNames ?: __String []) {
12259+ function createTupleType(elementTypes: readonly Type[], minLength = elementTypes.length, hasRestElement = false, readonly = false, namedMemberDeclarations ?: readonly (NamedTupleMember | ParameterDeclaration) []) {
1226612260 const arity = elementTypes.length;
1226712261 if (arity === 1 && hasRestElement) {
1226812262 return createArrayType(elementTypes[0], readonly);
1226912263 }
12270- const tupleType = getTupleTypeOfArity(arity, minLength, arity > 0 && hasRestElement, readonly, associatedNames );
12264+ const tupleType = getTupleTypeOfArity(arity, minLength, arity > 0 && hasRestElement, readonly, namedMemberDeclarations );
1227112265 return elementTypes.length ? createTypeReference(tupleType, elementTypes) : tupleType;
1227212266 }
1227312267
@@ -12282,7 +12276,7 @@ namespace ts {
1228212276 Math.max(0, tuple.minLength - index),
1228312277 tuple.hasRestElement,
1228412278 tuple.readonly,
12285- tuple.associatedNames && tuple.associatedNames .slice(index),
12279+ tuple.labeledElementDeclarations && tuple.labeledElementDeclarations .slice(index),
1228612280 );
1228712281 }
1228812282
@@ -14282,7 +14276,7 @@ namespace ts {
1428214276 minLength;
1428314277 const newReadonly = getModifiedReadonlyState(tupleType.target.readonly, modifiers);
1428414278 return contains(elementTypes, errorType) ? errorType :
14285- createTupleType(elementTypes, newMinLength, tupleType.target.hasRestElement, newReadonly, tupleType.target.associatedNames );
14279+ createTupleType(elementTypes, newMinLength, tupleType.target.hasRestElement, newReadonly, tupleType.target.labeledElementDeclarations );
1428614280 }
1428714281
1428814282 function instantiateMappedTypeTemplate(type: MappedType, key: Type, isOptional: boolean, mapper: TypeMapper) {
@@ -18539,7 +18533,7 @@ namespace ts {
1853918533 const elementTypes = map(getTypeArguments(source), t => inferReverseMappedType(t, target, constraint));
1854018534 const minLength = getMappedTypeModifiers(target) & MappedTypeModifiers.IncludeOptional ?
1854118535 getTypeReferenceArity(source) - (source.target.hasRestElement ? 1 : 0) : source.target.minLength;
18542- return createTupleType(elementTypes, minLength, source.target.hasRestElement, source.target.readonly, source.target.associatedNames );
18536+ return createTupleType(elementTypes, minLength, source.target.hasRestElement, source.target.readonly, source.target.labeledElementDeclarations );
1854318537 }
1854418538 // For all other object types we infer a new object type where the reverse mapping has been
1854518539 // applied to the type of each property.
@@ -25119,7 +25113,7 @@ namespace ts {
2511925113 function getArrayifiedType(type: Type) {
2512025114 return type.flags & TypeFlags.Union ? mapType(type, getArrayifiedType) :
2512125115 type.flags & (TypeFlags.Any | TypeFlags.Instantiable) || isMutableArrayOrTuple(type) ? type :
25122- isTupleType(type) ? createTupleType(getTypeArguments(type), type.target.minLength, type.target.hasRestElement, /*readonly*/ false, type.target.associatedNames ) :
25116+ isTupleType(type) ? createTupleType(getTypeArguments(type), type.target.minLength, type.target.hasRestElement, /*readonly*/ false, type.target.labeledElementDeclarations ) :
2512325117 createArrayType(getIndexedAccessType(type, numberType));
2512425118 }
2512525119
@@ -26979,6 +26973,11 @@ namespace ts {
2697926973 return type;
2698026974 }
2698126975
26976+ function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember) {
26977+ Debug.assert(isIdentifier(d.name)); // Parameter declarations could be binding patterns, but we only allow identifier names
26978+ return d.name.escapedText;
26979+ }
26980+
2698226981 function getParameterNameAtPosition(signature: Signature, pos: number) {
2698326982 const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
2698426983 if (pos < paramCount) {
@@ -26987,13 +26986,33 @@ namespace ts {
2698726986 const restParameter = signature.parameters[paramCount] || unknownSymbol;
2698826987 const restType = getTypeOfSymbol(restParameter);
2698926988 if (isTupleType(restType)) {
26990- const associatedNames = (<TupleType>(<TypeReference>restType).target).associatedNames ;
26989+ const associatedNames = (<TupleType>(<TypeReference>restType).target).labeledElementDeclarations ;
2699126990 const index = pos - paramCount;
26992- return associatedNames && associatedNames[index] || restParameter.escapedName + "_" + index as __String;
26991+ return associatedNames && getTupleElementLabel( associatedNames[index]) || restParameter.escapedName + "_" + index as __String;
2699326992 }
2699426993 return restParameter.escapedName;
2699526994 }
2699626995
26996+ function isValidDeclarationForTupleLabel(d: Declaration): d is NamedTupleMember | (ParameterDeclaration & { name: Identifier }) {
26997+ return d.kind === SyntaxKind.NamedTupleMember || (isParameter(d) && isIdentifier(d.name));
26998+ }
26999+
27000+ function getNameableDeclarationAtPosition(signature: Signature, pos: number) {
27001+ const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
27002+ if (pos < paramCount) {
27003+ const decl = signature.parameters[pos].valueDeclaration;
27004+ return decl && isValidDeclarationForTupleLabel(decl) ? decl : undefined;
27005+ }
27006+ const restParameter = signature.parameters[paramCount] || unknownSymbol;
27007+ const restType = getTypeOfSymbol(restParameter);
27008+ if (isTupleType(restType)) {
27009+ const associatedNames = (<TupleType>(<TypeReference>restType).target).labeledElementDeclarations;
27010+ const index = pos - paramCount;
27011+ return associatedNames && associatedNames[index];
27012+ }
27013+ return restParameter.valueDeclaration && isValidDeclarationForTupleLabel(restParameter.valueDeclaration) ? restParameter.valueDeclaration : undefined;
27014+ }
27015+
2699727016 function getTypeAtPosition(signature: Signature, pos: number): Type {
2699827017 return tryGetTypeAtPosition(signature, pos) || anyType;
2699927018 }
@@ -27024,14 +27043,26 @@ namespace ts {
2702427043 return restType;
2702527044 }
2702627045 const types = [];
27027- const names = [];
27046+ let names: (NamedTupleMember | ParameterDeclaration)[] | undefined = [];
2702827047 for (let i = pos; i < nonRestCount; i++) {
2702927048 types.push(getTypeAtPosition(source, i));
27030- names.push(getParameterNameAtPosition(source, i));
27049+ const name = getNameableDeclarationAtPosition(source, i);
27050+ if (name && names) {
27051+ names.push(name);
27052+ }
27053+ else {
27054+ names = undefined;
27055+ }
2703127056 }
2703227057 if (restType) {
2703327058 types.push(getIndexedAccessType(restType, numberType));
27034- names.push(getParameterNameAtPosition(source, nonRestCount));
27059+ const name = getNameableDeclarationAtPosition(source, nonRestCount);
27060+ if (name && names) {
27061+ names.push(name);
27062+ }
27063+ else {
27064+ names = undefined;
27065+ }
2703527066 }
2703627067 const minArgumentCount = getMinArgumentCount(source);
2703727068 const minLength = minArgumentCount < pos ? 0 : minArgumentCount - pos;
0 commit comments