@@ -13620,7 +13620,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
13620
13620
function getUniqAssociatedNamesFromTupleType(type: TupleTypeReference, restSymbol: Symbol) {
13621
13621
const associatedNamesMap = new Map<__String, number>();
13622
13622
return map(type.target.labeledElementDeclarations, (labeledElement, i) => {
13623
- const name = getTupleElementLabel(labeledElement, i, restSymbol);
13623
+ const name = getTupleElementLabel(labeledElement, i, type.target.elementFlags[i], restSymbol);
13624
13624
const prevCounter = associatedNamesMap.get(name);
13625
13625
if (prevCounter === undefined) {
13626
13626
associatedNamesMap.set(name, 1);
@@ -37268,35 +37268,71 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
37268
37268
37269
37269
/**
37270
37270
* Gets a tuple element label by recursively walking `ArrayBindingPattern` nodes in a `BindingName`.
37271
+ * @param node The source node from which to derive a label
37272
+ * @param index The index into the tuple
37273
+ * @param elementFlags The {@see ElementFlags} of the tuple element
37271
37274
*/
37272
- function getTupleElementLabelFromBindingName(node: BindingName, index: number): __String | undefined {
37273
- if (isArrayBindingPattern(node)) {
37274
- const elements = node.elements;
37275
- const lastElement = tryCast(lastOrUndefined(elements), isBindingElement);
37276
- const elementCount = elements.length - (lastElement?.dotDotDotToken ? 1 : 0);
37277
- if (index < elementCount) {
37278
- const element = elements[index];
37279
- if (isBindingElement(element) && isIdentifier(element.name)) {
37280
- return element.name.escapedText;
37275
+ function getTupleElementLabelFromBindingElement(node: BindingElement | ParameterDeclaration, index: number, elementFlags: ElementFlags): __String {
37276
+ switch (node.name.kind) {
37277
+ case SyntaxKind.Identifier: {
37278
+ const name = node.name.escapedText;
37279
+ if (node.dotDotDotToken) {
37280
+ // given
37281
+ // (...[x, y, ...z]: [number, number, ...number[]]) => ...
37282
+ // this produces
37283
+ // (x: number, y: number, ...z: number[]) => ...
37284
+ // which preserves rest elements of 'z'
37285
+
37286
+ // given
37287
+ // (...[x, y, ...z]: [number, number, ...[...number[], number]]) => ...
37288
+ // this produces
37289
+ // (x: number, y: number, ...z: number[], z_1: number) => ...
37290
+ // which preserves rest elements of z but gives distinct numbers to fixed elements of 'z'
37291
+ return elementFlags & ElementFlags.Variable ? name : `${name}_${index}` as __String;
37292
+ }
37293
+ else {
37294
+ // given
37295
+ // (...[x]: [number]) => ...
37296
+ // this produces
37297
+ // (x: number) => ...
37298
+ // which preserves fixed elements of 'x'
37299
+
37300
+ // given
37301
+ // (...[x]: ...number[]) => ...
37302
+ // this produces
37303
+ // (x_0: number) => ...
37304
+ // which which numbers fixed elements of 'x' whose tuple element type is variable
37305
+ return elementFlags & ElementFlags.Fixed ? name : `${name}_n` as __String;
37281
37306
}
37282
37307
}
37283
- else if (lastElement?.dotDotDotToken) {
37284
- const restIndex = index - elementCount;
37285
- return getTupleElementLabelFromBindingName(lastElement.name, restIndex);
37308
+ case SyntaxKind.ArrayBindingPattern: {
37309
+ if (node.dotDotDotToken) {
37310
+ const elements = node.name.elements;
37311
+ const lastElement = tryCast(lastOrUndefined(elements), isBindingElement);
37312
+ const elementCount = elements.length - (lastElement?.dotDotDotToken ? 1 : 0);
37313
+ if (index < elementCount) {
37314
+ const element = elements[index];
37315
+ if (isBindingElement(element)) {
37316
+ return getTupleElementLabelFromBindingElement(element, index, elementFlags);
37317
+ }
37318
+ }
37319
+ else if (lastElement?.dotDotDotToken) {
37320
+ return getTupleElementLabelFromBindingElement(lastElement, index - elementCount, elementFlags);
37321
+ }
37322
+ }
37323
+ break;
37286
37324
}
37287
37325
}
37288
- else if (isIdentifier(node)) {
37289
- return `${node.escapedText}_${index}` as __String;
37290
- }
37326
+ return `arg_${index}` as __String;
37291
37327
}
37292
37328
37293
37329
function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember): __String;
37294
- function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index: number, restSymbol?: Symbol): __String;
37295
- function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index = 0, restSymbol?: Symbol) {
37330
+ function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index: number, elementFlags: ElementFlags, restSymbol?: Symbol): __String;
37331
+ function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index = 0, elementFlags = ElementFlags.Fixed, restSymbol?: Symbol) {
37296
37332
if (!d) {
37297
37333
const restParameter = tryCast(restSymbol?.valueDeclaration, isParameter);
37298
- const label = restParameter && getTupleElementLabelFromBindingName (restParameter.name , index);
37299
- return label ?? `${restSymbol?.escapedName ?? "arg"}_${index}` as __String;
37334
+ return restParameter ? getTupleElementLabelFromBindingElement (restParameter, index, elementFlags) :
37335
+ `${restSymbol?.escapedName ?? "arg"}_${index}` as __String;
37300
37336
}
37301
37337
Debug.assert(isIdentifier(d.name)); // Parameter declarations could be binding patterns, but we only allow identifier names
37302
37338
return d.name.escapedText;
@@ -37310,9 +37346,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
37310
37346
const restParameter = signature.parameters[paramCount] || unknownSymbol;
37311
37347
const restType = overrideRestType || getTypeOfSymbol(restParameter);
37312
37348
if (isTupleType(restType)) {
37313
- const associatedNames = ((restType as TypeReference).target as TupleType).labeledElementDeclarations ;
37349
+ const tupleType = ((restType as TypeReference).target as TupleType);
37314
37350
const index = pos - paramCount;
37315
- return getTupleElementLabel(associatedNames?.[index], index, restParameter);
37351
+ const associatedName = tupleType.labeledElementDeclarations?.[index];
37352
+ const elementFlags = tupleType.elementFlags[index];
37353
+ return getTupleElementLabel(associatedName, index, elementFlags, restParameter);
37316
37354
}
37317
37355
return restParameter.escapedName;
37318
37356
}
0 commit comments