@@ -4568,9 +4568,9 @@ namespace ts {
4568
4568
createRestTypeNode(createArrayTypeNode(tupleConstituentNodes[i])) :
4569
4569
createOptionalTypeNode(tupleConstituentNodes[i]);
4570
4570
}
4571
- if ((type.target as TupleType).associatedNames ) {
4571
+ if ((type.target as TupleType).labeledElementDeclarations ) {
4572
4572
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]);
4574
4574
}
4575
4575
}
4576
4576
const tupleTypeNode = setEmitFlags(createTupleTypeNode(tupleConstituentNodes), EmitFlags.SingleLine);
@@ -12082,15 +12082,8 @@ namespace ts {
12082
12082
const lastElement = lastOrUndefined(node.elements);
12083
12083
const restElement = lastElement && unwrapNamedTupleMember(lastElement).kind === SyntaxKind.RestType ? lastElement : undefined;
12084
12084
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[]);
12094
12087
}
12095
12088
12096
12089
// Return true if the given type reference node is directly aliased or if it needs to be deferred
@@ -12187,7 +12180,7 @@ namespace ts {
12187
12180
//
12188
12181
// Note that the generic type created by this function has no symbol associated with it. The same
12189
12182
// 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 {
12191
12184
let typeParameters: TypeParameter[] | undefined;
12192
12185
const properties: Symbol[] = [];
12193
12186
const maxLength = hasRestElement ? arity - 1 : arity;
@@ -12198,6 +12191,7 @@ namespace ts {
12198
12191
if (i < maxLength) {
12199
12192
const property = createSymbol(SymbolFlags.Property | (i >= minLength ? SymbolFlags.Optional : 0),
12200
12193
"" + i as __String, readonly ? CheckFlags.Readonly : 0);
12194
+ property.tupleLabelDeclaration = namedMemberDeclarations?.[i];
12201
12195
property.type = typeParameter;
12202
12196
properties.push(property);
12203
12197
}
@@ -12227,25 +12221,25 @@ namespace ts {
12227
12221
type.minLength = minLength;
12228
12222
type.hasRestElement = hasRestElement;
12229
12223
type.readonly = readonly;
12230
- type.associatedNames = associatedNames ;
12224
+ type.labeledElementDeclarations = namedMemberDeclarations ;
12231
12225
return type;
12232
12226
}
12233
12227
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(",") : "");
12236
12230
let type = tupleTypes.get(key);
12237
12231
if (!type) {
12238
- tupleTypes.set(key, type = createTupleTypeOfArity(arity, minLength, hasRestElement, readonly, associatedNames ));
12232
+ tupleTypes.set(key, type = createTupleTypeOfArity(arity, minLength, hasRestElement, readonly, namedMemberDeclarations ));
12239
12233
}
12240
12234
return type;
12241
12235
}
12242
12236
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) []) {
12244
12238
const arity = elementTypes.length;
12245
12239
if (arity === 1 && hasRestElement) {
12246
12240
return createArrayType(elementTypes[0], readonly);
12247
12241
}
12248
- const tupleType = getTupleTypeOfArity(arity, minLength, arity > 0 && hasRestElement, readonly, associatedNames );
12242
+ const tupleType = getTupleTypeOfArity(arity, minLength, arity > 0 && hasRestElement, readonly, namedMemberDeclarations );
12249
12243
return elementTypes.length ? createTypeReference(tupleType, elementTypes) : tupleType;
12250
12244
}
12251
12245
@@ -12260,7 +12254,7 @@ namespace ts {
12260
12254
Math.max(0, tuple.minLength - index),
12261
12255
tuple.hasRestElement,
12262
12256
tuple.readonly,
12263
- tuple.associatedNames && tuple.associatedNames .slice(index),
12257
+ tuple.labeledElementDeclarations && tuple.labeledElementDeclarations .slice(index),
12264
12258
);
12265
12259
}
12266
12260
@@ -14260,7 +14254,7 @@ namespace ts {
14260
14254
minLength;
14261
14255
const newReadonly = getModifiedReadonlyState(tupleType.target.readonly, modifiers);
14262
14256
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 );
14264
14258
}
14265
14259
14266
14260
function instantiateMappedTypeTemplate(type: MappedType, key: Type, isOptional: boolean, mapper: TypeMapper) {
@@ -18517,7 +18511,7 @@ namespace ts {
18517
18511
const elementTypes = map(getTypeArguments(source), t => inferReverseMappedType(t, target, constraint));
18518
18512
const minLength = getMappedTypeModifiers(target) & MappedTypeModifiers.IncludeOptional ?
18519
18513
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 );
18521
18515
}
18522
18516
// For all other object types we infer a new object type where the reverse mapping has been
18523
18517
// applied to the type of each property.
@@ -25114,7 +25108,7 @@ namespace ts {
25114
25108
function getArrayifiedType(type: Type) {
25115
25109
return type.flags & TypeFlags.Union ? mapType(type, getArrayifiedType) :
25116
25110
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 ) :
25118
25112
createArrayType(getIndexedAccessType(type, numberType));
25119
25113
}
25120
25114
@@ -26974,6 +26968,11 @@ namespace ts {
26974
26968
return type;
26975
26969
}
26976
26970
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
+
26977
26976
function getParameterNameAtPosition(signature: Signature, pos: number) {
26978
26977
const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
26979
26978
if (pos < paramCount) {
@@ -26982,13 +26981,33 @@ namespace ts {
26982
26981
const restParameter = signature.parameters[paramCount] || unknownSymbol;
26983
26982
const restType = getTypeOfSymbol(restParameter);
26984
26983
if (isTupleType(restType)) {
26985
- const associatedNames = (<TupleType>(<TypeReference>restType).target).associatedNames ;
26984
+ const associatedNames = (<TupleType>(<TypeReference>restType).target).labeledElementDeclarations ;
26986
26985
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;
26988
26987
}
26989
26988
return restParameter.escapedName;
26990
26989
}
26991
26990
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
+
26992
27011
function getTypeAtPosition(signature: Signature, pos: number): Type {
26993
27012
return tryGetTypeAtPosition(signature, pos) || anyType;
26994
27013
}
@@ -27019,14 +27038,26 @@ namespace ts {
27019
27038
return restType;
27020
27039
}
27021
27040
const types = [];
27022
- const names = [];
27041
+ let names: (NamedTupleMember | ParameterDeclaration)[] | undefined = [];
27023
27042
for (let i = pos; i < nonRestCount; i++) {
27024
27043
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
+ }
27026
27051
}
27027
27052
if (restType) {
27028
27053
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
+ }
27030
27061
}
27031
27062
const minArgumentCount = getMinArgumentCount(source);
27032
27063
const minLength = minArgumentCount < pos ? 0 : minArgumentCount - pos;
0 commit comments