Derive tuple labels for rest elements from array binding patterns (#59045)

This commit is contained in:
Ron Buckton 2024-07-17 15:13:36 -04:00 committed by GitHub
parent a9139bfdfe
commit 369f2b0fb8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 7152 additions and 127 deletions

View File

@ -13574,20 +13574,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
function getExpandedParameters(sig: Signature, skipUnionExpanding?: boolean): readonly (readonly Symbol[])[] {
if (signatureHasRestParameter(sig)) {
const restIndex = sig.parameters.length - 1;
const restName = sig.parameters[restIndex].escapedName;
const restType = getTypeOfSymbol(sig.parameters[restIndex]);
const restSymbol = sig.parameters[restIndex];
const restType = getTypeOfSymbol(restSymbol);
if (isTupleType(restType)) {
return [expandSignatureParametersWithTupleMembers(restType, restIndex, restName)];
return [expandSignatureParametersWithTupleMembers(restType, restIndex, restSymbol)];
}
else if (!skipUnionExpanding && restType.flags & TypeFlags.Union && every((restType as UnionType).types, isTupleType)) {
return map((restType as UnionType).types, t => expandSignatureParametersWithTupleMembers(t as TupleTypeReference, restIndex, restName));
return map((restType as UnionType).types, t => expandSignatureParametersWithTupleMembers(t as TupleTypeReference, restIndex, restSymbol));
}
}
return [sig.parameters];
function expandSignatureParametersWithTupleMembers(restType: TupleTypeReference, restIndex: number, restName: __String) {
function expandSignatureParametersWithTupleMembers(restType: TupleTypeReference, restIndex: number, restSymbol: Symbol) {
const elementTypes = getTypeArguments(restType);
const associatedNames = getUniqAssociatedNamesFromTupleType(restType, restName);
const associatedNames = getUniqAssociatedNamesFromTupleType(restType, restSymbol);
const restParams = map(elementTypes, (t, i) => {
// Lookup the label from the individual tuple passed in before falling back to the signature `rest` parameter name
const name = associatedNames && associatedNames[i] ? associatedNames[i] :
@ -13602,20 +13602,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return concatenate(sig.parameters.slice(0, restIndex), restParams);
}
function getUniqAssociatedNamesFromTupleType(type: TupleTypeReference, restName: __String) {
const associatedNamesMap = new Map<__String, number>();
return map(type.target.labeledElementDeclarations, (labeledElement, i) => {
const name = getTupleElementLabel(labeledElement, i, restName);
const prevCounter = associatedNamesMap.get(name);
if (prevCounter === undefined) {
associatedNamesMap.set(name, 1);
return name;
function getUniqAssociatedNamesFromTupleType(type: TupleTypeReference, restSymbol: Symbol) {
const names = map(type.target.labeledElementDeclarations, (labeledElement, i) => getTupleElementLabel(labeledElement, i, type.target.elementFlags[i], restSymbol));
if (names) {
const duplicates: number[] = [];
const uniqueNames = new Set<__String>();
for (let i = 0; i < names.length; i++) {
const name = names[i];
if (!tryAddToSet(uniqueNames, name)) {
duplicates.push(i);
}
}
else {
associatedNamesMap.set(name, prevCounter + 1);
return `${name}_${prevCounter}` as __String;
const counters = new Map<__String, number>();
for (const i of duplicates) {
let counter = counters.get(names[i]) ?? 1;
let name: __String;
while (!tryAddToSet(uniqueNames, name = `${names[i]}_${counter}` as __String)) {
counter++;
}
names[i] = name;
counters.set(names[i], counter + 1);
}
});
}
return names;
}
}
@ -37247,11 +37256,73 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
);
}
/**
* Gets a tuple element label by recursively walking `ArrayBindingPattern` nodes in a `BindingName`.
* @param node The source node from which to derive a label
* @param index The index into the tuple
* @param elementFlags The {@see ElementFlags} of the tuple element
*/
function getTupleElementLabelFromBindingElement(node: BindingElement | ParameterDeclaration, index: number, elementFlags: ElementFlags): __String {
switch (node.name.kind) {
case SyntaxKind.Identifier: {
const name = node.name.escapedText;
if (node.dotDotDotToken) {
// given
// (...[x, y, ...z]: [number, number, ...number[]]) => ...
// this produces
// (x: number, y: number, ...z: number[]) => ...
// which preserves rest elements of 'z'
// given
// (...[x, y, ...z]: [number, number, ...[...number[], number]]) => ...
// this produces
// (x: number, y: number, ...z: number[], z_1: number) => ...
// which preserves rest elements of z but gives distinct numbers to fixed elements of 'z'
return elementFlags & ElementFlags.Variable ? name : `${name}_${index}` as __String;
}
else {
// given
// (...[x]: [number]) => ...
// this produces
// (x: number) => ...
// which preserves fixed elements of 'x'
// given
// (...[x]: ...number[]) => ...
// this produces
// (x_0: number) => ...
// which which numbers fixed elements of 'x' whose tuple element type is variable
return elementFlags & ElementFlags.Fixed ? name : `${name}_n` as __String;
}
}
case SyntaxKind.ArrayBindingPattern: {
if (node.dotDotDotToken) {
const elements = node.name.elements;
const lastElement = tryCast(lastOrUndefined(elements), isBindingElement);
const elementCount = elements.length - (lastElement?.dotDotDotToken ? 1 : 0);
if (index < elementCount) {
const element = elements[index];
if (isBindingElement(element)) {
return getTupleElementLabelFromBindingElement(element, index, elementFlags);
}
}
else if (lastElement?.dotDotDotToken) {
return getTupleElementLabelFromBindingElement(lastElement, index - elementCount, elementFlags);
}
}
break;
}
}
return `arg_${index}` as __String;
}
function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember): __String;
function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index: number, restParameterName?: __String): __String;
function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index?: number, restParameterName = "arg" as __String) {
function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index: number, elementFlags: ElementFlags, restSymbol?: Symbol): __String;
function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index = 0, elementFlags = ElementFlags.Fixed, restSymbol?: Symbol) {
if (!d) {
return `${restParameterName}_${index}` as __String;
const restParameter = tryCast(restSymbol?.valueDeclaration, isParameter);
return restParameter ? getTupleElementLabelFromBindingElement(restParameter, index, elementFlags) :
`${restSymbol?.escapedName ?? "arg"}_${index}` as __String;
}
Debug.assert(isIdentifier(d.name)); // Parameter declarations could be binding patterns, but we only allow identifier names
return d.name.escapedText;
@ -37265,9 +37336,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const restParameter = signature.parameters[paramCount] || unknownSymbol;
const restType = overrideRestType || getTypeOfSymbol(restParameter);
if (isTupleType(restType)) {
const associatedNames = ((restType as TypeReference).target as TupleType).labeledElementDeclarations;
const tupleType = (restType as TypeReference).target as TupleType;
const index = pos - paramCount;
return getTupleElementLabel(associatedNames?.[index], index, restParameter.escapedName);
const associatedName = tupleType.labeledElementDeclarations?.[index];
const elementFlags = tupleType.elementFlags[index];
return getTupleElementLabel(associatedName, index, elementFlags, restParameter);
}
return restParameter.escapedName;
}

View File

@ -40,10 +40,10 @@ declare const itNum: Iterable<number>
;(function(a, ...rest) {})('', true, ...itNum)
>(function(a, ...rest) {})('', true, ...itNum) : void
> : ^^^^
>(function(a, ...rest) {}) : (a: string, rest_0: boolean, ...rest_1: Iterable<number>[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>function(a, ...rest) {} : (a: string, rest_0: boolean, ...rest_1: Iterable<number>[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(function(a, ...rest) {}) : (a: string, rest_0: boolean, ...rest: Iterable<number>[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>function(a, ...rest) {} : (a: string, rest_0: boolean, ...rest: Iterable<number>[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>a : string
> : ^^^^^^
>rest : [boolean, ...Iterable<number>[]]

View File

@ -40,10 +40,10 @@ declare const itNum: Iterable<number>
;(function(a, ...rest) {})('', true, ...itNum)
>(function(a, ...rest) {})('', true, ...itNum) : void
> : ^^^^
>(function(a, ...rest) {}) : (a: string, rest_0: boolean, ...rest_1: number[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>function(a, ...rest) {} : (a: string, rest_0: boolean, ...rest_1: number[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(function(a, ...rest) {}) : (a: string, rest_0: boolean, ...rest: number[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>function(a, ...rest) {} : (a: string, rest_0: boolean, ...rest: number[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>a : string
> : ^^^^^^
>rest : [boolean, ...number[]]

View File

@ -64,14 +64,14 @@ declare let f04: (a: number, b: string, c: boolean, ...x: []) => void;
> : ^^
declare let f10: (...x: [number, string, ...boolean[]]) => void;
>f10 : (x_0: number, x_1: string, ...x_2: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f10 : (x_0: number, x_1: string, ...x: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>x : [number, string, ...boolean[]]
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
declare let f11: (a: number, ...x: [string, ...boolean[]]) => void;
>f11 : (a: number, x_0: string, ...x_1: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f11 : (a: number, x_0: string, ...x: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>a : number
> : ^^^^^^
>x : [string, ...boolean[]]
@ -108,8 +108,8 @@ declare const sn: [string, number];
f10(42, "hello");
>f10(42, "hello") : void
> : ^^^^
>f10 : (x_0: number, x_1: string, ...x_2: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f10 : (x_0: number, x_1: string, ...x: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>42 : 42
> : ^^
>"hello" : "hello"
@ -118,8 +118,8 @@ f10(42, "hello");
f10(42, "hello", true);
>f10(42, "hello", true) : void
> : ^^^^
>f10 : (x_0: number, x_1: string, ...x_2: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f10 : (x_0: number, x_1: string, ...x: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>42 : 42
> : ^^
>"hello" : "hello"
@ -130,8 +130,8 @@ f10(42, "hello", true);
f10(42, "hello", true, false);
>f10(42, "hello", true, false) : void
> : ^^^^
>f10 : (x_0: number, x_1: string, ...x_2: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f10 : (x_0: number, x_1: string, ...x: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>42 : 42
> : ^^
>"hello" : "hello"
@ -144,8 +144,8 @@ f10(42, "hello", true, false);
f10(t1[0], t1[1], t1[2], t1[3]);
>f10(t1[0], t1[1], t1[2], t1[3]) : void
> : ^^^^
>f10 : (x_0: number, x_1: string, ...x_2: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f10 : (x_0: number, x_1: string, ...x: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>t1[0] : number
> : ^^^^^^
>t1 : [number, string, ...boolean[]]
@ -174,8 +174,8 @@ f10(t1[0], t1[1], t1[2], t1[3]);
f10(...t1);
>f10(...t1) : void
> : ^^^^
>f10 : (x_0: number, x_1: string, ...x_2: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f10 : (x_0: number, x_1: string, ...x: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>...t1 : string | number | boolean
> : ^^^^^^^^^^^^^^^^^^^^^^^^^
>t1 : [number, string, ...boolean[]]
@ -184,8 +184,8 @@ f10(...t1);
f10(42, ...t2);
>f10(42, ...t2) : void
> : ^^^^
>f10 : (x_0: number, x_1: string, ...x_2: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f10 : (x_0: number, x_1: string, ...x: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>42 : 42
> : ^^
>...t2 : string | boolean
@ -196,8 +196,8 @@ f10(42, ...t2);
f10(42, "hello", ...t3);
>f10(42, "hello", ...t3) : void
> : ^^^^
>f10 : (x_0: number, x_1: string, ...x_2: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f10 : (x_0: number, x_1: string, ...x: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>42 : 42
> : ^^
>"hello" : "hello"
@ -210,8 +210,8 @@ f10(42, "hello", ...t3);
f10(42, "hello", true, ...t4);
>f10(42, "hello", true, ...t4) : void
> : ^^^^
>f10 : (x_0: number, x_1: string, ...x_2: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f10 : (x_0: number, x_1: string, ...x: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>42 : 42
> : ^^
>"hello" : "hello"
@ -226,8 +226,8 @@ f10(42, "hello", true, ...t4);
f10(42, "hello", true, ...t4, false, ...t3);
>f10(42, "hello", true, ...t4, false, ...t3) : void
> : ^^^^
>f10 : (x_0: number, x_1: string, ...x_2: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f10 : (x_0: number, x_1: string, ...x: boolean[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>42 : 42
> : ^^
>"hello" : "hello"
@ -248,8 +248,8 @@ f10(42, "hello", true, ...t4, false, ...t3);
f11(42, "hello");
>f11(42, "hello") : void
> : ^^^^
>f11 : (a: number, x_0: string, ...x_1: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f11 : (a: number, x_0: string, ...x: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>42 : 42
> : ^^
>"hello" : "hello"
@ -258,8 +258,8 @@ f11(42, "hello");
f11(42, "hello", true);
>f11(42, "hello", true) : void
> : ^^^^
>f11 : (a: number, x_0: string, ...x_1: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f11 : (a: number, x_0: string, ...x: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>42 : 42
> : ^^
>"hello" : "hello"
@ -270,8 +270,8 @@ f11(42, "hello", true);
f11(42, "hello", true, false);
>f11(42, "hello", true, false) : void
> : ^^^^
>f11 : (a: number, x_0: string, ...x_1: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f11 : (a: number, x_0: string, ...x: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>42 : 42
> : ^^
>"hello" : "hello"
@ -284,8 +284,8 @@ f11(42, "hello", true, false);
f11(t1[0], t1[1], t1[2], t1[3]);
>f11(t1[0], t1[1], t1[2], t1[3]) : void
> : ^^^^
>f11 : (a: number, x_0: string, ...x_1: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f11 : (a: number, x_0: string, ...x: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>t1[0] : number
> : ^^^^^^
>t1 : [number, string, ...boolean[]]
@ -314,8 +314,8 @@ f11(t1[0], t1[1], t1[2], t1[3]);
f11(...t1);
>f11(...t1) : void
> : ^^^^
>f11 : (a: number, x_0: string, ...x_1: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f11 : (a: number, x_0: string, ...x: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>...t1 : string | number | boolean
> : ^^^^^^^^^^^^^^^^^^^^^^^^^
>t1 : [number, string, ...boolean[]]
@ -324,8 +324,8 @@ f11(...t1);
f11(42, ...t2);
>f11(42, ...t2) : void
> : ^^^^
>f11 : (a: number, x_0: string, ...x_1: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f11 : (a: number, x_0: string, ...x: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>42 : 42
> : ^^
>...t2 : string | boolean
@ -336,8 +336,8 @@ f11(42, ...t2);
f11(42, "hello", ...t3);
>f11(42, "hello", ...t3) : void
> : ^^^^
>f11 : (a: number, x_0: string, ...x_1: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f11 : (a: number, x_0: string, ...x: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>42 : 42
> : ^^
>"hello" : "hello"
@ -350,8 +350,8 @@ f11(42, "hello", ...t3);
f11(42, "hello", true, ...t4);
>f11(42, "hello", true, ...t4) : void
> : ^^^^
>f11 : (a: number, x_0: string, ...x_1: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f11 : (a: number, x_0: string, ...x: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>42 : 42
> : ^^
>"hello" : "hello"
@ -366,8 +366,8 @@ f11(42, "hello", true, ...t4);
f11(42, "hello", true, ...t4, false, ...t3);
>f11(42, "hello", true, ...t4, false, ...t3) : void
> : ^^^^
>f11 : (a: number, x_0: string, ...x_1: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>f11 : (a: number, x_0: string, ...x: boolean[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>42 : 42
> : ^^
>"hello" : "hello"

View File

@ -59,8 +59,8 @@ class FooIterator {
}
function fun(...[a, ...b]) { }
>fun : (__0_0: any, ...__0_1: any[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>fun : (a: any, ...b: any[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>a : any
> : ^^^
>b : any[]
@ -69,8 +69,8 @@ function fun(...[a, ...b]) { }
fun(new FooIterator);
>fun(new FooIterator) : void
> : ^^^^
>fun : (__0_0: any, ...__0_1: any[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>fun : (a: any, ...b: any[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>new FooIterator : FooIterator
> : ^^^^^^^^^^^
>FooIterator : typeof FooIterator

View File

@ -2,7 +2,7 @@
=== iterableArrayPattern25.ts ===
function takeFirstTwoEntries(...[[k1, v1], [k2, v2]]) { }
>takeFirstTwoEntries : (__0_0: [any, any], __0_1: [any, any]) => void
>takeFirstTwoEntries : (arg_0: [any, any], arg_1: [any, any]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>k1 : any
> : ^^^
@ -16,7 +16,7 @@ function takeFirstTwoEntries(...[[k1, v1], [k2, v2]]) { }
takeFirstTwoEntries(new Map([["", 0], ["hello", 1]]));
>takeFirstTwoEntries(new Map([["", 0], ["hello", 1]])) : void
> : ^^^^
>takeFirstTwoEntries : (__0_0: [any, any], __0_1: [any, any]) => void
>takeFirstTwoEntries : (arg_0: [any, any], arg_1: [any, any]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>new Map([["", 0], ["hello", 1]]) : Map<string, number>
> : ^^^^^^^^^^^^^^^^^^^

View File

@ -2,8 +2,8 @@
=== restParameterWithBindingPattern2.ts ===
function a(...[a, b]) { }
>a : (__0_0: any, __0_1: any) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>a : (a: any, b: any) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^
>a : any
> : ^^^
>b : any

View File

@ -22,7 +22,7 @@ function b(...[...foo = []]: string[]) { }
> : ^^^^^^^^^^^
function c(...{0: a, length, 3: d}: [boolean, string, number]) { }
>c : (__0_0: boolean, __0_1: string, __0_2: number) => void
>c : (arg_0: boolean, arg_1: string, arg_2: number) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>a : boolean
> : ^^^^^^^
@ -32,8 +32,8 @@ function c(...{0: a, length, 3: d}: [boolean, string, number]) { }
> : ^^^^^^^^^
function d(...[a, , , d]: [boolean, string, number]) { }
>d : (__0_0: boolean, __0_1: string, __0_2: number) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>d : (a: boolean, arg_1: string, arg_2: number) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>a : boolean
> : ^^^^^^^
> : undefined
@ -44,7 +44,7 @@ function d(...[a, , , d]: [boolean, string, number]) { }
> : ^^^^^^^^^
function e(...{0: a = 1, 1: b = true, ...rest: rest}: [boolean, string, number]) { }
>e : (__0_0: boolean, __0_1: string, __0_2: number) => void
>e : (arg_0: boolean, arg_1: string, arg_2: number) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>a : boolean
> : ^^^^^^^

View File

@ -302,8 +302,8 @@ declare function f1(a: [(x: number) => number, ...((x: string) => number)[]]): v
> : ^^^^^^
declare function f2(...a: [(x: number) => number, ...((x: string) => number)[]]): void;
>f2 : (a_0: (x: number) => number, ...a_1: ((x: string) => number)[]) => void
> : ^^^^^^^ ^^ ^^^^^ ^^^^^^^^^^^^ ^^ ^^^^^ ^^^^^^^^
>f2 : (a_0: (x: number) => number, ...a: ((x: string) => number)[]) => void
> : ^^^^^^^ ^^ ^^^^^ ^^^^^^^^^^ ^^ ^^^^^ ^^^^^^^^
>a : [(x: number) => number, ...((x: string) => number)[]]
> : ^^ ^^ ^^^^^ ^^^^^^^ ^^ ^^^^^ ^^^^
>x : number
@ -356,8 +356,8 @@ f1([x => x * 2, x => x.length, x => x.charCodeAt(0)]);
f2(x => x * 2, x => x.length, x => x.charCodeAt(0));
>f2(x => x * 2, x => x.length, x => x.charCodeAt(0)) : void
> : ^^^^
>f2 : (a_0: (x: number) => number, ...a_1: ((x: string) => number)[]) => void
> : ^^^^^^^ ^^ ^^^^^ ^^^^^^^^^^^^ ^^ ^^^^^ ^^^^^^^^
>f2 : (a_0: (x: number) => number, ...a: ((x: string) => number)[]) => void
> : ^^^^^^^ ^^ ^^^^^ ^^^^^^^^^^ ^^ ^^^^^ ^^^^^^^^
>x => x * 2 : (x: number) => number
> : ^ ^^^^^^^^^^^^^^^^^^^
>x : number

View File

@ -192,10 +192,10 @@ declare const t2: [number, boolean, ...string[]];
(function (...x){})(...t2);
>(function (...x){})(...t2) : void
> : ^^^^
>(function (...x){}) : (x_0: number, x_1: boolean, ...x_2: string[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>function (...x){} : (x_0: number, x_1: boolean, ...x_2: string[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(function (...x){}) : (x_0: number, x_1: boolean, ...x: string[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>function (...x){} : (x_0: number, x_1: boolean, ...x: string[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>x : [number, boolean, ...string[]]
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>...t2 : string | number | boolean
@ -206,10 +206,10 @@ declare const t2: [number, boolean, ...string[]];
(function (a, ...x){})(...t2);
>(function (a, ...x){})(...t2) : void
> : ^^^^
>(function (a, ...x){}) : (a: number, x_0: boolean, ...x_1: string[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>function (a, ...x){} : (a: number, x_0: boolean, ...x_1: string[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(function (a, ...x){}) : (a: number, x_0: boolean, ...x: string[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>function (a, ...x){} : (a: number, x_0: boolean, ...x: string[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>a : number
> : ^^^^^^
>x : [boolean, ...string[]]
@ -260,8 +260,8 @@ declare const t2: [number, boolean, ...string[]];
declare function f2(cb: (...args: typeof t2) => void): void;
>f2 : (cb: (...args: typeof t2) => void) => void
> : ^ ^^ ^^^^^
>cb : (args_0: number, args_1: boolean, ...args_2: string[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>cb : (args_0: number, args_1: boolean, ...args: string[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>args : [number, boolean, ...string[]]
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>t2 : [number, boolean, ...string[]]
@ -286,8 +286,8 @@ f2((...x) => {})
> : ^^^^
>f2 : (cb: (...args: typeof t2) => void) => void
> : ^ ^^ ^^^^^
>(...x) => {} : (x_0: number, x_1: boolean, ...x_2: string[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(...x) => {} : (x_0: number, x_1: boolean, ...x: string[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>x : [number, boolean, ...string[]]
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -296,8 +296,8 @@ f2((a, ...x) => {})
> : ^^^^
>f2 : (cb: (...args: typeof t2) => void) => void
> : ^ ^^ ^^^^^
>(a, ...x) => {} : (a: number, x_0: boolean, ...x_1: string[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(a, ...x) => {} : (a: number, x_0: boolean, ...x: string[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>a : number
> : ^^^^^^
>x : [boolean, ...string[]]
@ -360,10 +360,10 @@ declare const t3: [boolean, ...string[]];
(function (...x){})(1, ...t3);
>(function (...x){})(1, ...t3) : void
> : ^^^^
>(function (...x){}) : (x_0: number, x_1: boolean, ...x_2: string[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>function (...x){} : (x_0: number, x_1: boolean, ...x_2: string[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(function (...x){}) : (x_0: number, x_1: boolean, ...x: string[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>function (...x){} : (x_0: number, x_1: boolean, ...x: string[]) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>x : [number, boolean, ...string[]]
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>1 : 1
@ -376,10 +376,10 @@ declare const t3: [boolean, ...string[]];
(function (a, ...x){})(1, ...t3);
>(function (a, ...x){})(1, ...t3) : void
> : ^^^^
>(function (a, ...x){}) : (a: number, x_0: boolean, ...x_1: string[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>function (a, ...x){} : (a: number, x_0: boolean, ...x_1: string[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(function (a, ...x){}) : (a: number, x_0: boolean, ...x: string[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>function (a, ...x){} : (a: number, x_0: boolean, ...x: string[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>a : number
> : ^^^^^^
>x : [boolean, ...string[]]
@ -436,8 +436,8 @@ declare const t3: [boolean, ...string[]];
declare function f3(cb: (x: number, ...args: typeof t3) => void): void;
>f3 : (cb: (x: number, ...args: typeof t3) => void) => void
> : ^ ^^ ^^^^^
>cb : (x: number, args_0: boolean, ...args_1: string[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>cb : (x: number, args_0: boolean, ...args: string[]) => void
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>x : number
> : ^^^^^^
>args : [boolean, ...string[]]
@ -474,8 +474,8 @@ f3((a, ...x) => {})
> : ^^^^
>f3 : (cb: (x: number, ...args: typeof t3) => void) => void
> : ^ ^^ ^^^^^
>(a, ...x) => {} : (a: number, x_0: boolean, ...x_1: string[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(a, ...x) => {} : (a: number, x_0: boolean, ...x: string[]) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>a : number
> : ^^^^^^
>x : [boolean, ...string[]]
@ -552,10 +552,10 @@ function f4<T extends any[]>(t: T) {
(function(a, ...x){})(1, 2, ...t);
>(function(a, ...x){})(1, 2, ...t) : void
> : ^^^^
>(function(a, ...x){}) : (a: number, x_0: number, ...x_1: T) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>function(a, ...x){} : (a: number, x_0: number, ...x_1: T) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>(function(a, ...x){}) : (a: number, x_0: number, ...x: T) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>function(a, ...x){} : (a: number, x_0: number, ...x: T) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>a : number
> : ^^^^^^
>x : [number, ...T]

File diff suppressed because it is too large Load Diff

View File

@ -823,7 +823,7 @@ declare function getOrgUser(id: string, orgId: number, options?: {
y?: number;
z?: boolean;
}): void;
declare function callApi<T extends unknown[] = [], U = void>(method: (...args: [...T, object]) => U): (...args_0: T) => U;
declare function callApi<T extends unknown[] = [], U = void>(method: (...args: [...T, object]) => U): (...args: T) => U;
type Numbers = number[];
type Unbounded = [...Numbers, boolean];
declare const data: Unbounded;

View File

@ -2218,16 +2218,16 @@ declare function getOrgUser(id: string, orgId: number, options?: { y?: number, z
> : ^^^^^^^^^^^^^^^^^^^
function callApi<T extends unknown[] = [], U = void>(method: (...args: [...T, object]) => U) {
>callApi : <T extends unknown[] = [], U = void>(method: (...args: [...T, object]) => U) => (...args_0: T) => U
> : ^ ^^^^^^^^^ ^^^^^^^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^
>callApi : <T extends unknown[] = [], U = void>(method: (...args: [...T, object]) => U) => (...args: T) => U
> : ^ ^^^^^^^^^ ^^^^^^^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^
>method : (...args: [...T, object]) => U
> : ^^^^ ^^ ^^^^^
>args : [...T, object]
> : ^^^^^^^^^^^^^^
return (...args: [...T]) => method(...args, {});
>(...args: [...T]) => method(...args, {}) : (...args_0: T) => U
> : ^^^^^^^^^^^^^^^^^^^
>(...args: [...T]) => method(...args, {}) : (...args: T) => U
> : ^^^^^^^^^^^^^^^^^
>args : [...T]
> : ^^^^^^
>method(...args, {}) : U
@ -2245,16 +2245,16 @@ function callApi<T extends unknown[] = [], U = void>(method: (...args: [...T, ob
callApi(getUser);
>callApi(getUser) : (id: string) => string
> : ^^^^^^^^^^^^^^^^^^^^^^
>callApi : <T extends unknown[] = [], U = void>(method: (...args: [...T, object]) => U) => (...args_0: T) => U
> : ^ ^^^^^^^^^ ^^^^^^^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^
>callApi : <T extends unknown[] = [], U = void>(method: (...args: [...T, object]) => U) => (...args: T) => U
> : ^ ^^^^^^^^^ ^^^^^^^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^
>getUser : (id: string, options?: { x?: string; }) => string
> : ^ ^^ ^^ ^^^ ^^^^^
callApi(getOrgUser);
>callApi(getOrgUser) : (id: string, orgId: number) => void
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>callApi : <T extends unknown[] = [], U = void>(method: (...args: [...T, object]) => U) => (...args_0: T) => U
> : ^ ^^^^^^^^^ ^^^^^^^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^
>callApi : <T extends unknown[] = [], U = void>(method: (...args: [...T, object]) => U) => (...args: T) => U
> : ^ ^^^^^^^^^ ^^^^^^^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^
>getOrgUser : (id: string, orgId: number, options?: { y?: number; z?: boolean; }) => void
> : ^ ^^ ^^ ^^ ^^ ^^^ ^^^^^

View File

@ -0,0 +1,70 @@
/// <reference path='fourslash.ts' />
// from: https://github.com/microsoft/TypeScript/pull/57619
//// interface AppleInfo {
//// color: "green" | "red";
//// }
////
//// interface BananaInfo {
//// curvature: number;
//// }
////
//// type FruitAndInfo1 = ["apple", AppleInfo] | ["banana", BananaInfo];
////
//// function logFruitTuple1(...[fruit, info]: FruitAndInfo1) {}
//// logFruitTuple1(/*1*/);
////
//// function logFruitTuple2(...[, info]: FruitAndInfo1) {}
//// logFruitTuple2(/*2*/);
//// logFruitTuple2("apple", /*3*/);
////
//// function logFruitTuple3(...[fruit, ...rest]: FruitAndInfo1) {}
//// logFruitTuple3(/*4*/);
//// logFruitTuple3("apple", /*5*/);
//// function logFruitTuple4(...[fruit, ...[info]]: FruitAndInfo1) {}
//// logFruitTuple4(/*6*/);
//// logFruitTuple4("apple", /*7*/);
////
//// type FruitAndInfo2 = ["apple", ...AppleInfo[]] | ["banana", ...BananaInfo[]];
////
//// function logFruitTuple5(...[fruit, firstInfo]: FruitAndInfo2) {}
//// logFruitTuple5(/*8*/);
//// logFruitTuple5("apple", /*9*/);
////
//// function logFruitTuple6(...[fruit, ...fruitInfo]: FruitAndInfo2) {}
//// logFruitTuple6(/*10*/);
//// logFruitTuple6("apple", /*11*/);
////
//// type FruitAndInfo3 = ["apple", ...AppleInfo[], number] | ["banana", ...BananaInfo[], number];
////
//// function logFruitTuple7(...[fruit, fruitInfoOrNumber, secondFruitInfoOrNumber]: FruitAndInfo3) {}
//// logFruitTuple7(/*12*/);
//// logFruitTuple7("apple", /*13*/);
//// logFruitTuple7("apple", { color: "red" }, /*14*/);
////
//// function logFruitTuple8(...[fruit, , secondFruitInfoOrNumber]: FruitAndInfo3) {}
//// logFruitTuple8(/*15*/);
//// logFruitTuple8("apple", /*16*/);
//// logFruitTuple8("apple", { color: "red" }, /*17*/);
////
//// function logFruitTuple9(...[...[fruit, fruitInfoOrNumber, secondFruitInfoOrNumber]]: FruitAndInfo3) {}
//// logFruitTuple9(/*18*/);
//// logFruitTuple9("apple", /*19*/);
//// logFruitTuple9("apple", { color: "red" }, /*20*/);
////
//// function logFruitTuple10(...[fruit, {}, secondFruitInfoOrNumber]: FruitAndInfo3) {}
//// logFruitTuple10(/*21*/);
//// logFruitTuple10("apple", /*22*/);
//// logFruitTuple10("apple", { color: "red" }, /*23*/);
////
//// function logFruitTuple11(...{}: FruitAndInfo3) {}
//// logFruitTuple11(/*24*/);
//// logFruitTuple11("apple", /*25*/);
//// logFruitTuple11("apple", { color: "red" }, /*26*/);
//// function withPair(...[first, second]: [number, named: string]) {}
//// withPair(/*27*/);
//// withPair(101, /*28*/);
verify.baselineSignatureHelp();

View File

@ -29,7 +29,7 @@ verify.signatureHelp(
},
{
marker: "3",
text: "complex(item: string, another: string, rest_0: (err: Error) => void, ...rest_1: object[]): void",
text: "complex(item: string, another: string, rest_0: (err: Error) => void, ...rest: object[]): void",
overloadsCount: 3,
isVariadic: true,
},