@@ -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);
@@ -12104,15 +12104,8 @@ namespace ts {
12104
12104
const lastElement = lastOrUndefined(node.elements);
12105
12105
const restElement = lastElement && unwrapNamedTupleMember(lastElement).kind === SyntaxKind.RestType ? lastElement : undefined;
12106
12106
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[]);
12116
12109
}
12117
12110
12118
12111
// Return true if the given type reference node is directly aliased or if it needs to be deferred
@@ -12209,7 +12202,7 @@ namespace ts {
12209
12202
//
12210
12203
// Note that the generic type created by this function has no symbol associated with it. The same
12211
12204
// 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 {
12213
12206
let typeParameters: TypeParameter[] | undefined;
12214
12207
const properties: Symbol[] = [];
12215
12208
const maxLength = hasRestElement ? arity - 1 : arity;
@@ -12220,6 +12213,7 @@ namespace ts {
12220
12213
if (i < maxLength) {
12221
12214
const property = createSymbol(SymbolFlags.Property | (i >= minLength ? SymbolFlags.Optional : 0),
12222
12215
"" + i as __String, readonly ? CheckFlags.Readonly : 0);
12216
+ property.tupleLabelDeclaration = namedMemberDeclarations?.[i];
12223
12217
property.type = typeParameter;
12224
12218
properties.push(property);
12225
12219
}
@@ -12249,25 +12243,25 @@ namespace ts {
12249
12243
type.minLength = minLength;
12250
12244
type.hasRestElement = hasRestElement;
12251
12245
type.readonly = readonly;
12252
- type.associatedNames = associatedNames ;
12246
+ type.labeledElementDeclarations = namedMemberDeclarations ;
12253
12247
return type;
12254
12248
}
12255
12249
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(",") : "");
12258
12252
let type = tupleTypes.get(key);
12259
12253
if (!type) {
12260
- tupleTypes.set(key, type = createTupleTypeOfArity(arity, minLength, hasRestElement, readonly, associatedNames ));
12254
+ tupleTypes.set(key, type = createTupleTypeOfArity(arity, minLength, hasRestElement, readonly, namedMemberDeclarations ));
12261
12255
}
12262
12256
return type;
12263
12257
}
12264
12258
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) []) {
12266
12260
const arity = elementTypes.length;
12267
12261
if (arity === 1 && hasRestElement) {
12268
12262
return createArrayType(elementTypes[0], readonly);
12269
12263
}
12270
- const tupleType = getTupleTypeOfArity(arity, minLength, arity > 0 && hasRestElement, readonly, associatedNames );
12264
+ const tupleType = getTupleTypeOfArity(arity, minLength, arity > 0 && hasRestElement, readonly, namedMemberDeclarations );
12271
12265
return elementTypes.length ? createTypeReference(tupleType, elementTypes) : tupleType;
12272
12266
}
12273
12267
@@ -12282,7 +12276,7 @@ namespace ts {
12282
12276
Math.max(0, tuple.minLength - index),
12283
12277
tuple.hasRestElement,
12284
12278
tuple.readonly,
12285
- tuple.associatedNames && tuple.associatedNames .slice(index),
12279
+ tuple.labeledElementDeclarations && tuple.labeledElementDeclarations .slice(index),
12286
12280
);
12287
12281
}
12288
12282
@@ -14282,7 +14276,7 @@ namespace ts {
14282
14276
minLength;
14283
14277
const newReadonly = getModifiedReadonlyState(tupleType.target.readonly, modifiers);
14284
14278
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 );
14286
14280
}
14287
14281
14288
14282
function instantiateMappedTypeTemplate(type: MappedType, key: Type, isOptional: boolean, mapper: TypeMapper) {
@@ -18539,7 +18533,7 @@ namespace ts {
18539
18533
const elementTypes = map(getTypeArguments(source), t => inferReverseMappedType(t, target, constraint));
18540
18534
const minLength = getMappedTypeModifiers(target) & MappedTypeModifiers.IncludeOptional ?
18541
18535
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 );
18543
18537
}
18544
18538
// For all other object types we infer a new object type where the reverse mapping has been
18545
18539
// applied to the type of each property.
@@ -25119,7 +25113,7 @@ namespace ts {
25119
25113
function getArrayifiedType(type: Type) {
25120
25114
return type.flags & TypeFlags.Union ? mapType(type, getArrayifiedType) :
25121
25115
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 ) :
25123
25117
createArrayType(getIndexedAccessType(type, numberType));
25124
25118
}
25125
25119
@@ -26979,6 +26973,11 @@ namespace ts {
26979
26973
return type;
26980
26974
}
26981
26975
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
+
26982
26981
function getParameterNameAtPosition(signature: Signature, pos: number) {
26983
26982
const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
26984
26983
if (pos < paramCount) {
@@ -26987,13 +26986,33 @@ namespace ts {
26987
26986
const restParameter = signature.parameters[paramCount] || unknownSymbol;
26988
26987
const restType = getTypeOfSymbol(restParameter);
26989
26988
if (isTupleType(restType)) {
26990
- const associatedNames = (<TupleType>(<TypeReference>restType).target).associatedNames ;
26989
+ const associatedNames = (<TupleType>(<TypeReference>restType).target).labeledElementDeclarations ;
26991
26990
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;
26993
26992
}
26994
26993
return restParameter.escapedName;
26995
26994
}
26996
26995
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
+
26997
27016
function getTypeAtPosition(signature: Signature, pos: number): Type {
26998
27017
return tryGetTypeAtPosition(signature, pos) || anyType;
26999
27018
}
@@ -27024,14 +27043,26 @@ namespace ts {
27024
27043
return restType;
27025
27044
}
27026
27045
const types = [];
27027
- const names = [];
27046
+ let names: (NamedTupleMember | ParameterDeclaration)[] | undefined = [];
27028
27047
for (let i = pos; i < nonRestCount; i++) {
27029
27048
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
+ }
27031
27056
}
27032
27057
if (restType) {
27033
27058
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
+ }
27035
27066
}
27036
27067
const minArgumentCount = getMinArgumentCount(source);
27037
27068
const minLength = minArgumentCount < pos ? 0 : minArgumentCount - pos;
0 commit comments