From 533f7decfebfc2d726de1394895503151921d84e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 31 Mar 2023 10:01:39 +0200 Subject: [PATCH 1/4] Fixed an issue with spreading generic types with tuple constraints into calls --- src/compiler/checker.ts | 8 ++ .../reference/arraySpreadInCall.errors.txt | 32 +++++++ .../reference/arraySpreadInCall.symbols | 92 +++++++++++++++++++ .../reference/arraySpreadInCall.types | 81 ++++++++++++++++ .../es6/spread/arraySpreadInCall.ts | 32 +++++++ 5 files changed, 245 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fcf5c3854c960..95aa8e10aaa7c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -32711,6 +32711,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const arg = args[i]; // We can call checkExpressionCached because spread expressions never have a contextual type. const spreadType = arg.kind === SyntaxKind.SpreadElement && (flowLoopCount ? checkExpression((arg as SpreadElement).expression) : checkExpressionCached((arg as SpreadElement).expression)); + const constraint = spreadType && getConstraintOfType(spreadType); if (spreadType && isTupleType(spreadType)) { forEach(getTypeArguments(spreadType), (t, i) => { const flags = spreadType.target.elementFlags[i]; @@ -32719,6 +32720,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { effectiveArgs.push(syntheticArg); }); } + else if (constraint && isTupleType(constraint) && every(constraint.target.elementFlags, flag => !(flag & ElementFlags.Variable))) { + forEach(getTypeArguments(constraint), (_, i) => { + const syntheticArg = createSyntheticExpression(arg, getTypeOfPropertyOfType(spreadType, "" + i as __String)!, + /*isSpread*/ false, constraint.target.labeledElementDeclarations?.[i]); + effectiveArgs.push(syntheticArg); + }); + } else { effectiveArgs.push(arg); } diff --git a/tests/baselines/reference/arraySpreadInCall.errors.txt b/tests/baselines/reference/arraySpreadInCall.errors.txt index a28479767edd6..49bda8708a0d5 100644 --- a/tests/baselines/reference/arraySpreadInCall.errors.txt +++ b/tests/baselines/reference/arraySpreadInCall.errors.txt @@ -26,4 +26,36 @@ tests/cases/conformance/es6/spread/arraySpreadInCall.ts(21,12): error TS2554: Ex ~~~~~~~~~~~~~~~ !!! error TS2554: Expected 0-1 arguments, but got 2. + // repro from #53541 + class T { + fn(name?: string, sex?: number): void {} + } + + class M { + constructor(public m: X) {} + + fn(...args: Parameters) { + this.m.fn(...args); + } + } + + // repro from #53541#issuecomment-1487859044 + interface HasMethod { + method(first?: string, second?: number): void; + method2(...args: [name: string, sex?: number] | [other: number]): void; + } + + function fn21( + instance: HasMethodLike, + ...args: Parameters + ) { + instance.method(...args); + } + + function fn22( + instance: HasMethodLike, + ...args: Parameters + ) { + instance.method2(...args); + } \ No newline at end of file diff --git a/tests/baselines/reference/arraySpreadInCall.symbols b/tests/baselines/reference/arraySpreadInCall.symbols index 359c6d52d123b..964b2bfcafc7f 100644 --- a/tests/baselines/reference/arraySpreadInCall.symbols +++ b/tests/baselines/reference/arraySpreadInCall.symbols @@ -70,4 +70,96 @@ action.run(...[100, 'foo']) // error >action : Symbol(action, Decl(arraySpreadInCall.ts, 19, 13)) >run : Symbol(IAction.run, Decl(arraySpreadInCall.ts, 16, 19)) +// repro from #53541 +class T { +>T : Symbol(T, Decl(arraySpreadInCall.ts, 20, 27)) + + fn(name?: string, sex?: number): void {} +>fn : Symbol(T.fn, Decl(arraySpreadInCall.ts, 23, 9)) +>name : Symbol(name, Decl(arraySpreadInCall.ts, 24, 5)) +>sex : Symbol(sex, Decl(arraySpreadInCall.ts, 24, 19)) +} + +class M { +>M : Symbol(M, Decl(arraySpreadInCall.ts, 25, 1)) +>X : Symbol(X, Decl(arraySpreadInCall.ts, 27, 8)) +>T : Symbol(T, Decl(arraySpreadInCall.ts, 20, 27)) + + constructor(public m: X) {} +>m : Symbol(M.m, Decl(arraySpreadInCall.ts, 28, 14)) +>X : Symbol(X, Decl(arraySpreadInCall.ts, 27, 8)) + + fn(...args: Parameters) { +>fn : Symbol(M.fn, Decl(arraySpreadInCall.ts, 28, 29)) +>args : Symbol(args, Decl(arraySpreadInCall.ts, 30, 5)) +>Parameters : Symbol(Parameters, Decl(lib.es5.d.ts, --, --)) +>X : Symbol(X, Decl(arraySpreadInCall.ts, 27, 8)) + + this.m.fn(...args); +>this.m.fn : Symbol(T.fn, Decl(arraySpreadInCall.ts, 23, 9)) +>this.m : Symbol(M.m, Decl(arraySpreadInCall.ts, 28, 14)) +>this : Symbol(M, Decl(arraySpreadInCall.ts, 25, 1)) +>m : Symbol(M.m, Decl(arraySpreadInCall.ts, 28, 14)) +>fn : Symbol(T.fn, Decl(arraySpreadInCall.ts, 23, 9)) +>args : Symbol(args, Decl(arraySpreadInCall.ts, 30, 5)) + } +} + +// repro from #53541#issuecomment-1487859044 +interface HasMethod { +>HasMethod : Symbol(HasMethod, Decl(arraySpreadInCall.ts, 33, 1)) + + method(first?: string, second?: number): void; +>method : Symbol(HasMethod.method, Decl(arraySpreadInCall.ts, 36, 21)) +>first : Symbol(first, Decl(arraySpreadInCall.ts, 37, 9)) +>second : Symbol(second, Decl(arraySpreadInCall.ts, 37, 24)) + + method2(...args: [name: string, sex?: number] | [other: number]): void; +>method2 : Symbol(HasMethod.method2, Decl(arraySpreadInCall.ts, 37, 48)) +>args : Symbol(args, Decl(arraySpreadInCall.ts, 38, 10)) +} + +function fn21( +>fn21 : Symbol(fn21, Decl(arraySpreadInCall.ts, 39, 1)) +>HasMethodLike : Symbol(HasMethodLike, Decl(arraySpreadInCall.ts, 41, 14)) +>HasMethod : Symbol(HasMethod, Decl(arraySpreadInCall.ts, 33, 1)) + + instance: HasMethodLike, +>instance : Symbol(instance, Decl(arraySpreadInCall.ts, 41, 47)) +>HasMethodLike : Symbol(HasMethodLike, Decl(arraySpreadInCall.ts, 41, 14)) + + ...args: Parameters +>args : Symbol(args, Decl(arraySpreadInCall.ts, 42, 26)) +>Parameters : Symbol(Parameters, Decl(lib.es5.d.ts, --, --)) +>HasMethodLike : Symbol(HasMethodLike, Decl(arraySpreadInCall.ts, 41, 14)) + +) { + instance.method(...args); +>instance.method : Symbol(HasMethod.method, Decl(arraySpreadInCall.ts, 36, 21)) +>instance : Symbol(instance, Decl(arraySpreadInCall.ts, 41, 47)) +>method : Symbol(HasMethod.method, Decl(arraySpreadInCall.ts, 36, 21)) +>args : Symbol(args, Decl(arraySpreadInCall.ts, 42, 26)) +} + +function fn22( +>fn22 : Symbol(fn22, Decl(arraySpreadInCall.ts, 46, 1)) +>HasMethodLike : Symbol(HasMethodLike, Decl(arraySpreadInCall.ts, 48, 14)) +>HasMethod : Symbol(HasMethod, Decl(arraySpreadInCall.ts, 33, 1)) + + instance: HasMethodLike, +>instance : Symbol(instance, Decl(arraySpreadInCall.ts, 48, 47)) +>HasMethodLike : Symbol(HasMethodLike, Decl(arraySpreadInCall.ts, 48, 14)) + + ...args: Parameters +>args : Symbol(args, Decl(arraySpreadInCall.ts, 49, 26)) +>Parameters : Symbol(Parameters, Decl(lib.es5.d.ts, --, --)) +>HasMethodLike : Symbol(HasMethodLike, Decl(arraySpreadInCall.ts, 48, 14)) + +) { + instance.method2(...args); +>instance.method2 : Symbol(HasMethod.method2, Decl(arraySpreadInCall.ts, 37, 48)) +>instance : Symbol(instance, Decl(arraySpreadInCall.ts, 48, 47)) +>method2 : Symbol(HasMethod.method2, Decl(arraySpreadInCall.ts, 37, 48)) +>args : Symbol(args, Decl(arraySpreadInCall.ts, 49, 26)) +} diff --git a/tests/baselines/reference/arraySpreadInCall.types b/tests/baselines/reference/arraySpreadInCall.types index 7f06c4be8f14c..37a03dbad56bf 100644 --- a/tests/baselines/reference/arraySpreadInCall.types +++ b/tests/baselines/reference/arraySpreadInCall.types @@ -139,4 +139,85 @@ action.run(...[100, 'foo']) // error >100 : 100 >'foo' : "foo" +// repro from #53541 +class T { +>T : T + + fn(name?: string, sex?: number): void {} +>fn : (name?: string, sex?: number) => void +>name : string | undefined +>sex : number | undefined +} + +class M { +>M : M + + constructor(public m: X) {} +>m : X + + fn(...args: Parameters) { +>fn : (...args: Parameters) => void +>args : Parameters + + this.m.fn(...args); +>this.m.fn(...args) : void +>this.m.fn : (name?: string | undefined, sex?: number | undefined) => void +>this.m : X +>this : this +>m : X +>fn : (name?: string | undefined, sex?: number | undefined) => void +>...args : string | number | undefined +>args : Parameters + } +} + +// repro from #53541#issuecomment-1487859044 +interface HasMethod { + method(first?: string, second?: number): void; +>method : (first?: string, second?: number) => void +>first : string | undefined +>second : number | undefined + + method2(...args: [name: string, sex?: number] | [other: number]): void; +>method2 : (...args: [name: string, sex?: number] | [other: number]) => void +>args : [name: string, sex?: number | undefined] | [other: number] +} + +function fn21( +>fn21 : (instance: HasMethodLike, ...args: Parameters) => void + + instance: HasMethodLike, +>instance : HasMethodLike + + ...args: Parameters +>args : Parameters + +) { + instance.method(...args); +>instance.method(...args) : void +>instance.method : (first?: string | undefined, second?: number | undefined) => void +>instance : HasMethodLike +>method : (first?: string | undefined, second?: number | undefined) => void +>...args : string | number | undefined +>args : Parameters +} + +function fn22( +>fn22 : (instance: HasMethodLike, ...args: Parameters) => void + + instance: HasMethodLike, +>instance : HasMethodLike + + ...args: Parameters +>args : Parameters + +) { + instance.method2(...args); +>instance.method2(...args) : void +>instance.method2 : (...args: [name: string, sex?: number | undefined] | [other: number]) => void +>instance : HasMethodLike +>method2 : (...args: [name: string, sex?: number | undefined] | [other: number]) => void +>...args : string | number | undefined +>args : Parameters +} diff --git a/tests/cases/conformance/es6/spread/arraySpreadInCall.ts b/tests/cases/conformance/es6/spread/arraySpreadInCall.ts index 9077256106ba8..68c68ac0aefb2 100644 --- a/tests/cases/conformance/es6/spread/arraySpreadInCall.ts +++ b/tests/cases/conformance/es6/spread/arraySpreadInCall.ts @@ -23,3 +23,35 @@ interface IAction { declare const action: IAction action.run(...[100, 'foo']) // error +// repro from #53541 +class T { + fn(name?: string, sex?: number): void {} +} + +class M { + constructor(public m: X) {} + + fn(...args: Parameters) { + this.m.fn(...args); + } +} + +// repro from #53541#issuecomment-1487859044 +interface HasMethod { + method(first?: string, second?: number): void; + method2(...args: [name: string, sex?: number] | [other: number]): void; +} + +function fn21( + instance: HasMethodLike, + ...args: Parameters +) { + instance.method(...args); +} + +function fn22( + instance: HasMethodLike, + ...args: Parameters +) { + instance.method2(...args); +} From e35d71f28fefb66c86c029cc87375f3f74ddf655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 1 Apr 2023 00:04:03 +0200 Subject: [PATCH 2/4] simplify the fix --- src/compiler/checker.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 95aa8e10aaa7c..160774b2efc4a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -32720,10 +32720,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { effectiveArgs.push(syntheticArg); }); } - else if (constraint && isTupleType(constraint) && every(constraint.target.elementFlags, flag => !(flag & ElementFlags.Variable))) { + else if (constraint && isTupleType(constraint)) { forEach(getTypeArguments(constraint), (_, i) => { - const syntheticArg = createSyntheticExpression(arg, getTypeOfPropertyOfType(spreadType, "" + i as __String)!, - /*isSpread*/ false, constraint.target.labeledElementDeclarations?.[i]); + const isVariable = !!(constraint.target.elementFlags[i] & ElementFlags.Variable); + const syntheticArg = createSyntheticExpression(arg, !isVariable ? getTypeOfPropertyOfType(spreadType, "" + i as __String)! : spreadType, + /*isSpread*/ isVariable, constraint.target.labeledElementDeclarations?.[i]); effectiveArgs.push(syntheticArg); }); } From bca909dd4efba6f4b1b51defb896b26deee1da61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 1 Apr 2023 10:58:28 +0200 Subject: [PATCH 3/4] Create deferred indexed access type --- src/compiler/checker.ts | 2 +- .../reference/genericRestParameters1.types | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 160774b2efc4a..aa77e3466cfe6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -32723,7 +32723,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (constraint && isTupleType(constraint)) { forEach(getTypeArguments(constraint), (_, i) => { const isVariable = !!(constraint.target.elementFlags[i] & ElementFlags.Variable); - const syntheticArg = createSyntheticExpression(arg, !isVariable ? getTypeOfPropertyOfType(spreadType, "" + i as __String)! : spreadType, + const syntheticArg = createSyntheticExpression(arg, !isVariable ? getIndexedAccessType(spreadType, getStringLiteralType("" + i))! : spreadType, /*isSpread*/ isVariable, constraint.target.labeledElementDeclarations?.[i]); effectiveArgs.push(syntheticArg); }); diff --git a/tests/baselines/reference/genericRestParameters1.types b/tests/baselines/reference/genericRestParameters1.types index cbc4e9410755c..92c733013122f 100644 --- a/tests/baselines/reference/genericRestParameters1.types +++ b/tests/baselines/reference/genericRestParameters1.types @@ -258,8 +258,8 @@ function g10(u: U, v: V) { >u : U let x2 = f10(...v); // V ->x2 : V ->f10(...v) : V +>x2 : [V["0"], V["1"]] +>f10(...v) : [V["0"], V["1"]] >f10 : (...args: T) => T >...v : number >v : V @@ -273,8 +273,8 @@ function g10(u: U, v: V) { >u : U let x4 = f10(...u, ...v); // (string | number)[] ->x4 : [...U, ...V] ->f10(...u, ...v) : [...U, ...V] +>x4 : [...U, V["0"], V["1"]] +>f10(...u, ...v) : [...U, V["0"], V["1"]] >f10 : (...args: T) => T >...u : string >u : U @@ -367,8 +367,8 @@ function g11(u: U, v: V) { >u : U let x2 = f11(...v); // V ->x2 : V ->f11(...v) : V +>x2 : [V["0"], V["1"]] +>f11(...v) : [V["0"], V["1"]] >f11 : (...args: T) => T >...v : number >v : V @@ -382,8 +382,8 @@ function g11(u: U, v: V) { >u : U let x4 = f11(...u, ...v); // (string | number)[] ->x4 : [...U, ...V] ->f11(...u, ...v) : [...U, ...V] +>x4 : [...U, V["0"], V["1"]] +>f11(...u, ...v) : [...U, V["0"], V["1"]] >f11 : (...args: T) => T >...u : string >u : U From 2774d575c5a557a4479706ddde022c0599323a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 1 Apr 2023 14:52:15 +0200 Subject: [PATCH 4/4] Update comments containing "expected" results in `genericRestParameters1` test --- .../genericRestParameters1.errors.txt | 26 +++++----- .../reference/genericRestParameters1.js | 52 +++++++++---------- .../reference/genericRestParameters1.symbols | 26 +++++----- .../reference/genericRestParameters1.types | 26 +++++----- .../types/rest/genericRestParameters1.ts | 26 +++++----- 5 files changed, 78 insertions(+), 78 deletions(-) diff --git a/tests/baselines/reference/genericRestParameters1.errors.txt b/tests/baselines/reference/genericRestParameters1.errors.txt index b3d13ab2f652d..cc9e55e307591 100644 --- a/tests/baselines/reference/genericRestParameters1.errors.txt +++ b/tests/baselines/reference/genericRestParameters1.errors.txt @@ -27,7 +27,7 @@ tests/cases/conformance/types/rest/genericRestParameters1.ts(164,1): error TS232 f1(42, "hello", ...t1); f1(42, "hello", true, ...t0); f1(ns[0], ns[1], true); - f1(...ns, true); // FIXME: Error, since ...ns is considered as string|number here + f1(...ns, true); f2(42, "hello", true); f2(t3[0], t3[1], t3[2]); @@ -36,7 +36,7 @@ tests/cases/conformance/types/rest/genericRestParameters1.ts(164,1): error TS232 f2(42, "hello", ...t1); f2(42, "hello", true, ...t0); f2(ns[0], ns[1], true); - f2(...ns, true); // FIXME: Error, since ...ns is considered as string|number here + f2(...ns, true); declare function f10(...args: T): T; @@ -48,13 +48,13 @@ tests/cases/conformance/types/rest/genericRestParameters1.ts(164,1): error TS232 const x15 = f10(42, ...t2); // [number, string, boolean] const x16 = f10(42, "hello", ...t1); // [number, string, boolean] const x17 = f10(42, "hello", true, ...t0); // [number, string, boolean] - const x18 = f10(...ns, true); // (string | number | boolean)[] + const x18 = f10(...ns, true); // [number, string, boolean] function g10(u: U, v: V) { let x1 = f10(...u); // U - let x2 = f10(...v); // V - let x3 = f10(1, ...u); // [number, ...string[]] - let x4 = f10(...u, ...v); // (string | number)[] + let x2 = f10(...v); // [V["0"], V["1"]] + let x3 = f10(1, ...u); // [number, ...U] + let x4 = f10(...u, ...v); // [...U, V["0"], V["1"]] } declare function f11(...args: T): T; @@ -67,13 +67,13 @@ tests/cases/conformance/types/rest/genericRestParameters1.ts(164,1): error TS232 const z15 = f11(42, ...t2); // [42, string, boolean] const z16 = f11(42, "hello", ...t1); // [42, "hello", boolean] const z17 = f11(42, "hello", true, ...t0); // [42, "hello", true] - const z18 = f11(...ns, true); // (string | number | true)[] + const z18 = f11(...ns, true); // [number, string, true] function g11(u: U, v: V) { let x1 = f11(...u); // U - let x2 = f11(...v); // V - let x3 = f11(1, ...u); // [1, ...string[]] - let x4 = f11(...u, ...v); // (string | number)[] + let x2 = f11(...v); // [V["0"], V["1"]] + let x3 = f11(1, ...u); // [1, ...U] + let x4 = f11(...u, ...v); // [...U, V["0"], V["1"]] } function call(f: (...args: T) => U, ...args: T) { @@ -90,7 +90,7 @@ tests/cases/conformance/types/rest/genericRestParameters1.ts(164,1): error TS232 let x20 = call((x, y) => x + y, 10, 20); // number let x21 = call((x, y) => x + y, 10, "hello"); // string let x22 = call(f15, "hello", 42); // string | number - let x23 = call(f16, "hello", 42); // unknown + let x23 = call(f16, "hello", 42); // string | number let x24 = call<[string, number], string | number>(f16, "hello", 42); // string | number let x30 = callr(sn, (x, y) => x + y); // string @@ -114,8 +114,8 @@ tests/cases/conformance/types/rest/genericRestParameters1.ts(164,1): error TS232 declare const g20: (x: number, y?: string, z?: boolean) => string[]; - const g21 = bind(g20, 42); // (y: string, z: boolean) => string[] - const g22 = bind(g21, "hello"); // (z: boolean) => string[] + const g21 = bind(g20, 42); // (y?: string, z?: boolean) => string[] + const g22 = bind(g21, "hello"); // (z?: boolean) => string[] const g23 = bind(g22, true); // () => string[] g20(42, "hello", true); diff --git a/tests/baselines/reference/genericRestParameters1.js b/tests/baselines/reference/genericRestParameters1.js index 00ffe4a66d9bd..30f9b0608a3bc 100644 --- a/tests/baselines/reference/genericRestParameters1.js +++ b/tests/baselines/reference/genericRestParameters1.js @@ -20,7 +20,7 @@ f1(42, ...t2); f1(42, "hello", ...t1); f1(42, "hello", true, ...t0); f1(ns[0], ns[1], true); -f1(...ns, true); // FIXME: Error, since ...ns is considered as string|number here +f1(...ns, true); f2(42, "hello", true); f2(t3[0], t3[1], t3[2]); @@ -29,7 +29,7 @@ f2(42, ...t2); f2(42, "hello", ...t1); f2(42, "hello", true, ...t0); f2(ns[0], ns[1], true); -f2(...ns, true); // FIXME: Error, since ...ns is considered as string|number here +f2(...ns, true); declare function f10(...args: T): T; @@ -41,13 +41,13 @@ const x14 = f10(...t3); // [number, string, boolean] const x15 = f10(42, ...t2); // [number, string, boolean] const x16 = f10(42, "hello", ...t1); // [number, string, boolean] const x17 = f10(42, "hello", true, ...t0); // [number, string, boolean] -const x18 = f10(...ns, true); // (string | number | boolean)[] +const x18 = f10(...ns, true); // [number, string, boolean] function g10(u: U, v: V) { let x1 = f10(...u); // U - let x2 = f10(...v); // V - let x3 = f10(1, ...u); // [number, ...string[]] - let x4 = f10(...u, ...v); // (string | number)[] + let x2 = f10(...v); // [V["0"], V["1"]] + let x3 = f10(1, ...u); // [number, ...U] + let x4 = f10(...u, ...v); // [...U, V["0"], V["1"]] } declare function f11(...args: T): T; @@ -60,13 +60,13 @@ const z14 = f11(...t3); // [number, string, boolean] const z15 = f11(42, ...t2); // [42, string, boolean] const z16 = f11(42, "hello", ...t1); // [42, "hello", boolean] const z17 = f11(42, "hello", true, ...t0); // [42, "hello", true] -const z18 = f11(...ns, true); // (string | number | true)[] +const z18 = f11(...ns, true); // [number, string, true] function g11(u: U, v: V) { let x1 = f11(...u); // U - let x2 = f11(...v); // V - let x3 = f11(1, ...u); // [1, ...string[]] - let x4 = f11(...u, ...v); // (string | number)[] + let x2 = f11(...v); // [V["0"], V["1"]] + let x3 = f11(1, ...u); // [1, ...U] + let x4 = f11(...u, ...v); // [...U, V["0"], V["1"]] } function call(f: (...args: T) => U, ...args: T) { @@ -83,7 +83,7 @@ declare function f16(a: A, b: B): A | B; let x20 = call((x, y) => x + y, 10, 20); // number let x21 = call((x, y) => x + y, 10, "hello"); // string let x22 = call(f15, "hello", 42); // string | number -let x23 = call(f16, "hello", 42); // unknown +let x23 = call(f16, "hello", 42); // string | number let x24 = call<[string, number], string | number>(f16, "hello", 42); // string | number let x30 = callr(sn, (x, y) => x + y); // string @@ -107,8 +107,8 @@ f23(); declare const g20: (x: number, y?: string, z?: boolean) => string[]; -const g21 = bind(g20, 42); // (y: string, z: boolean) => string[] -const g22 = bind(g21, "hello"); // (z: boolean) => string[] +const g21 = bind(g20, 42); // (y?: string, z?: boolean) => string[] +const g22 = bind(g21, "hello"); // (z?: boolean) => string[] const g23 = bind(g22, true); // () => string[] g20(42, "hello", true); @@ -185,7 +185,7 @@ f1.apply(void 0, __spreadArray([42], t2, false)); f1.apply(void 0, __spreadArray([42, "hello"], t1, false)); f1.apply(void 0, __spreadArray([42, "hello", true], t0, false)); f1(ns[0], ns[1], true); -f1.apply(void 0, __spreadArray(__spreadArray([], ns, false), [true], false)); // FIXME: Error, since ...ns is considered as string|number here +f1.apply(void 0, __spreadArray(__spreadArray([], ns, false), [true], false)); f2(42, "hello", true); f2(t3[0], t3[1], t3[2]); f2.apply(void 0, t3); @@ -193,7 +193,7 @@ f2.apply(void 0, __spreadArray([42], t2, false)); f2.apply(void 0, __spreadArray([42, "hello"], t1, false)); f2.apply(void 0, __spreadArray([42, "hello", true], t0, false)); f2(ns[0], ns[1], true); -f2.apply(void 0, __spreadArray(__spreadArray([], ns, false), [true], false)); // FIXME: Error, since ...ns is considered as string|number here +f2.apply(void 0, __spreadArray(__spreadArray([], ns, false), [true], false)); var x10 = f10(42, "hello", true); // [number, string, boolean] var x11 = f10(42, "hello"); // [number, string] var x12 = f10(42); // [number] @@ -202,12 +202,12 @@ var x14 = f10.apply(void 0, t3); // [number, string, boolean] var x15 = f10.apply(void 0, __spreadArray([42], t2, false)); // [number, string, boolean] var x16 = f10.apply(void 0, __spreadArray([42, "hello"], t1, false)); // [number, string, boolean] var x17 = f10.apply(void 0, __spreadArray([42, "hello", true], t0, false)); // [number, string, boolean] -var x18 = f10.apply(void 0, __spreadArray(__spreadArray([], ns, false), [true], false)); // (string | number | boolean)[] +var x18 = f10.apply(void 0, __spreadArray(__spreadArray([], ns, false), [true], false)); // [number, string, boolean] function g10(u, v) { var x1 = f10.apply(void 0, u); // U - var x2 = f10.apply(void 0, v); // V - var x3 = f10.apply(void 0, __spreadArray([1], u, false)); // [number, ...string[]] - var x4 = f10.apply(void 0, __spreadArray(__spreadArray([], u, false), v, false)); // (string | number)[] + var x2 = f10.apply(void 0, v); // [V["0"], V["1"]] + var x3 = f10.apply(void 0, __spreadArray([1], u, false)); // [number, ...U] + var x4 = f10.apply(void 0, __spreadArray(__spreadArray([], u, false), v, false)); // [...U, V["0"], V["1"]] } var z10 = f11(42, "hello", true); // [42, "hello", true] var z11 = f11(42, "hello"); // [42, "hello"] @@ -217,12 +217,12 @@ var z14 = f11.apply(void 0, t3); // [number, string, boolean] var z15 = f11.apply(void 0, __spreadArray([42], t2, false)); // [42, string, boolean] var z16 = f11.apply(void 0, __spreadArray([42, "hello"], t1, false)); // [42, "hello", boolean] var z17 = f11.apply(void 0, __spreadArray([42, "hello", true], t0, false)); // [42, "hello", true] -var z18 = f11.apply(void 0, __spreadArray(__spreadArray([], ns, false), [true], false)); // (string | number | true)[] +var z18 = f11.apply(void 0, __spreadArray(__spreadArray([], ns, false), [true], false)); // [number, string, true] function g11(u, v) { var x1 = f11.apply(void 0, u); // U - var x2 = f11.apply(void 0, v); // V - var x3 = f11.apply(void 0, __spreadArray([1], u, false)); // [1, ...string[]] - var x4 = f11.apply(void 0, __spreadArray(__spreadArray([], u, false), v, false)); // (string | number)[] + var x2 = f11.apply(void 0, v); // [V["0"], V["1"]] + var x3 = f11.apply(void 0, __spreadArray([1], u, false)); // [1, ...U] + var x4 = f11.apply(void 0, __spreadArray(__spreadArray([], u, false), v, false)); // [...U, V["0"], V["1"]] } function call(f) { var args = []; @@ -237,7 +237,7 @@ function callr(args, f) { var x20 = call(function (x, y) { return x + y; }, 10, 20); // number var x21 = call(function (x, y) { return x + y; }, 10, "hello"); // string var x22 = call(f15, "hello", 42); // string | number -var x23 = call(f16, "hello", 42); // unknown +var x23 = call(f16, "hello", 42); // string | number var x24 = call(f16, "hello", 42); // string | number var x30 = callr(sn, function (x, y) { return x + y; }); // string var x31 = callr(sn, f15); // string | number @@ -258,8 +258,8 @@ f20(42, "hello", true); f21("hello", true); f22(true); f23(); -var g21 = bind(g20, 42); // (y: string, z: boolean) => string[] -var g22 = bind(g21, "hello"); // (z: boolean) => string[] +var g21 = bind(g20, 42); // (y?: string, z?: boolean) => string[] +var g22 = bind(g21, "hello"); // (z?: boolean) => string[] var g23 = bind(g22, true); // () => string[] g20(42, "hello", true); g20(42, "hello"); diff --git a/tests/baselines/reference/genericRestParameters1.symbols b/tests/baselines/reference/genericRestParameters1.symbols index 56f1bc6cf5869..6e7654ce2233d 100644 --- a/tests/baselines/reference/genericRestParameters1.symbols +++ b/tests/baselines/reference/genericRestParameters1.symbols @@ -70,7 +70,7 @@ f1(ns[0], ns[1], true); >ns : Symbol(ns, Decl(genericRestParameters1.ts, 11, 13)) >1 : Symbol(1) -f1(...ns, true); // FIXME: Error, since ...ns is considered as string|number here +f1(...ns, true); >f1 : Symbol(f1, Decl(genericRestParameters1.ts, 0, 11)) >ns : Symbol(ns, Decl(genericRestParameters1.ts, 11, 13)) @@ -109,7 +109,7 @@ f2(ns[0], ns[1], true); >ns : Symbol(ns, Decl(genericRestParameters1.ts, 11, 13)) >1 : Symbol(1) -f2(...ns, true); // FIXME: Error, since ...ns is considered as string|number here +f2(...ns, true); >f2 : Symbol(f2, Decl(genericRestParameters1.ts, 1, 11)) >ns : Symbol(ns, Decl(genericRestParameters1.ts, 11, 13)) @@ -156,7 +156,7 @@ const x17 = f10(42, "hello", true, ...t0); // [number, string, boolean] >f10 : Symbol(f10, Decl(genericRestParameters1.ts, 30, 16)) >t0 : Symbol(t0, Decl(genericRestParameters1.ts, 9, 13)) -const x18 = f10(...ns, true); // (string | number | boolean)[] +const x18 = f10(...ns, true); // [number, string, boolean] >x18 : Symbol(x18, Decl(genericRestParameters1.ts, 42, 5)) >f10 : Symbol(f10, Decl(genericRestParameters1.ts, 30, 16)) >ns : Symbol(ns, Decl(genericRestParameters1.ts, 11, 13)) @@ -175,17 +175,17 @@ function g10(u: U, v: V) { >f10 : Symbol(f10, Decl(genericRestParameters1.ts, 30, 16)) >u : Symbol(u, Decl(genericRestParameters1.ts, 44, 61)) - let x2 = f10(...v); // V + let x2 = f10(...v); // [V["0"], V["1"]] >x2 : Symbol(x2, Decl(genericRestParameters1.ts, 46, 7)) >f10 : Symbol(f10, Decl(genericRestParameters1.ts, 30, 16)) >v : Symbol(v, Decl(genericRestParameters1.ts, 44, 66)) - let x3 = f10(1, ...u); // [number, ...string[]] + let x3 = f10(1, ...u); // [number, ...U] >x3 : Symbol(x3, Decl(genericRestParameters1.ts, 47, 7)) >f10 : Symbol(f10, Decl(genericRestParameters1.ts, 30, 16)) >u : Symbol(u, Decl(genericRestParameters1.ts, 44, 61)) - let x4 = f10(...u, ...v); // (string | number)[] + let x4 = f10(...u, ...v); // [...U, V["0"], V["1"]] >x4 : Symbol(x4, Decl(genericRestParameters1.ts, 48, 7)) >f10 : Symbol(f10, Decl(genericRestParameters1.ts, 30, 16)) >u : Symbol(u, Decl(genericRestParameters1.ts, 44, 61)) @@ -235,7 +235,7 @@ const z17 = f11(42, "hello", true, ...t0); // [42, "hello", true] >f11 : Symbol(f11, Decl(genericRestParameters1.ts, 49, 1)) >t0 : Symbol(t0, Decl(genericRestParameters1.ts, 9, 13)) -const z18 = f11(...ns, true); // (string | number | true)[] +const z18 = f11(...ns, true); // [number, string, true] >z18 : Symbol(z18, Decl(genericRestParameters1.ts, 61, 5)) >f11 : Symbol(f11, Decl(genericRestParameters1.ts, 49, 1)) >ns : Symbol(ns, Decl(genericRestParameters1.ts, 11, 13)) @@ -254,17 +254,17 @@ function g11(u: U, v: V) { >f11 : Symbol(f11, Decl(genericRestParameters1.ts, 49, 1)) >u : Symbol(u, Decl(genericRestParameters1.ts, 63, 61)) - let x2 = f11(...v); // V + let x2 = f11(...v); // [V["0"], V["1"]] >x2 : Symbol(x2, Decl(genericRestParameters1.ts, 65, 7)) >f11 : Symbol(f11, Decl(genericRestParameters1.ts, 49, 1)) >v : Symbol(v, Decl(genericRestParameters1.ts, 63, 66)) - let x3 = f11(1, ...u); // [1, ...string[]] + let x3 = f11(1, ...u); // [1, ...U] >x3 : Symbol(x3, Decl(genericRestParameters1.ts, 66, 7)) >f11 : Symbol(f11, Decl(genericRestParameters1.ts, 49, 1)) >u : Symbol(u, Decl(genericRestParameters1.ts, 63, 61)) - let x4 = f11(...u, ...v); // (string | number)[] + let x4 = f11(...u, ...v); // [...U, V["0"], V["1"]] >x4 : Symbol(x4, Decl(genericRestParameters1.ts, 67, 7)) >f11 : Symbol(f11, Decl(genericRestParameters1.ts, 49, 1)) >u : Symbol(u, Decl(genericRestParameters1.ts, 63, 61)) @@ -340,7 +340,7 @@ let x22 = call(f15, "hello", 42); // string | number >call : Symbol(call, Decl(genericRestParameters1.ts, 68, 1)) >f15 : Symbol(f15, Decl(genericRestParameters1.ts, 76, 1)) -let x23 = call(f16, "hello", 42); // unknown +let x23 = call(f16, "hello", 42); // string | number >x23 : Symbol(x23, Decl(genericRestParameters1.ts, 84, 3)) >call : Symbol(call, Decl(genericRestParameters1.ts, 68, 1)) >f16 : Symbol(f16, Decl(genericRestParameters1.ts, 78, 60)) @@ -432,12 +432,12 @@ declare const g20: (x: number, y?: string, z?: boolean) => string[]; >y : Symbol(y, Decl(genericRestParameters1.ts, 106, 30)) >z : Symbol(z, Decl(genericRestParameters1.ts, 106, 42)) -const g21 = bind(g20, 42); // (y: string, z: boolean) => string[] +const g21 = bind(g20, 42); // (y?: string, z?: boolean) => string[] >g21 : Symbol(g21, Decl(genericRestParameters1.ts, 108, 5)) >bind : Symbol(bind, Decl(genericRestParameters1.ts, 89, 25)) >g20 : Symbol(g20, Decl(genericRestParameters1.ts, 106, 13)) -const g22 = bind(g21, "hello"); // (z: boolean) => string[] +const g22 = bind(g21, "hello"); // (z?: boolean) => string[] >g22 : Symbol(g22, Decl(genericRestParameters1.ts, 109, 5)) >bind : Symbol(bind, Decl(genericRestParameters1.ts, 89, 25)) >g21 : Symbol(g21, Decl(genericRestParameters1.ts, 108, 5)) diff --git a/tests/baselines/reference/genericRestParameters1.types b/tests/baselines/reference/genericRestParameters1.types index 92c733013122f..a659a5c9e8673 100644 --- a/tests/baselines/reference/genericRestParameters1.types +++ b/tests/baselines/reference/genericRestParameters1.types @@ -98,7 +98,7 @@ f1(ns[0], ns[1], true); >1 : 1 >true : true -f1(...ns, true); // FIXME: Error, since ...ns is considered as string|number here +f1(...ns, true); >f1(...ns, true) : void >f1 : (x_0: number, x_1: string, x_2: boolean) => void >...ns : string | number @@ -166,7 +166,7 @@ f2(ns[0], ns[1], true); >1 : 1 >true : true -f2(...ns, true); // FIXME: Error, since ...ns is considered as string|number here +f2(...ns, true); >f2(...ns, true) : void >f2 : (x0: number, x1: string, x2: boolean) => void >...ns : string | number @@ -237,7 +237,7 @@ const x17 = f10(42, "hello", true, ...t0); // [number, string, boolean] >...t0 : never >t0 : [] -const x18 = f10(...ns, true); // (string | number | boolean)[] +const x18 = f10(...ns, true); // [number, string, boolean] >x18 : [number, string, boolean] >f10(...ns, true) : [number, string, boolean] >f10 : (...args: T) => T @@ -257,14 +257,14 @@ function g10(u: U, v: V) { >...u : string >u : U - let x2 = f10(...v); // V + let x2 = f10(...v); // [V["0"], V["1"]] >x2 : [V["0"], V["1"]] >f10(...v) : [V["0"], V["1"]] >f10 : (...args: T) => T >...v : number >v : V - let x3 = f10(1, ...u); // [number, ...string[]] + let x3 = f10(1, ...u); // [number, ...U] >x3 : [number, ...U] >f10(1, ...u) : [number, ...U] >f10 : (...args: T) => T @@ -272,7 +272,7 @@ function g10(u: U, v: V) { >...u : string >u : U - let x4 = f10(...u, ...v); // (string | number)[] + let x4 = f10(...u, ...v); // [...U, V["0"], V["1"]] >x4 : [...U, V["0"], V["1"]] >f10(...u, ...v) : [...U, V["0"], V["1"]] >f10 : (...args: T) => T @@ -346,7 +346,7 @@ const z17 = f11(42, "hello", true, ...t0); // [42, "hello", true] >...t0 : never >t0 : [] -const z18 = f11(...ns, true); // (string | number | true)[] +const z18 = f11(...ns, true); // [number, string, true] >z18 : [number, string, true] >f11(...ns, true) : [number, string, true] >f11 : (...args: T) => T @@ -366,14 +366,14 @@ function g11(u: U, v: V) { >...u : string >u : U - let x2 = f11(...v); // V + let x2 = f11(...v); // [V["0"], V["1"]] >x2 : [V["0"], V["1"]] >f11(...v) : [V["0"], V["1"]] >f11 : (...args: T) => T >...v : number >v : V - let x3 = f11(1, ...u); // [1, ...string[]] + let x3 = f11(1, ...u); // [1, ...U] >x3 : [1, ...U] >f11(1, ...u) : [1, ...U] >f11 : (...args: T) => T @@ -381,7 +381,7 @@ function g11(u: U, v: V) { >...u : string >u : U - let x4 = f11(...u, ...v); // (string | number)[] + let x4 = f11(...u, ...v); // [...U, V["0"], V["1"]] >x4 : [...U, V["0"], V["1"]] >f11(...u, ...v) : [...U, V["0"], V["1"]] >f11 : (...args: T) => T @@ -461,7 +461,7 @@ let x22 = call(f15, "hello", 42); // string | number >"hello" : "hello" >42 : 42 -let x23 = call(f16, "hello", 42); // unknown +let x23 = call(f16, "hello", 42); // string | number >x23 : string | number >call(f16, "hello", 42) : string | number >call : (f: (...args: T) => U, ...args: T) => U @@ -575,14 +575,14 @@ declare const g20: (x: number, y?: string, z?: boolean) => string[]; >y : string | undefined >z : boolean | undefined -const g21 = bind(g20, 42); // (y: string, z: boolean) => string[] +const g21 = bind(g20, 42); // (y?: string, z?: boolean) => string[] >g21 : (y?: string | undefined, z?: boolean | undefined) => string[] >bind(g20, 42) : (y?: string | undefined, z?: boolean | undefined) => string[] >bind : (f: (x: T, ...rest: U) => V, x: T) => (...rest: U) => V >g20 : (x: number, y?: string | undefined, z?: boolean | undefined) => string[] >42 : 42 -const g22 = bind(g21, "hello"); // (z: boolean) => string[] +const g22 = bind(g21, "hello"); // (z?: boolean) => string[] >g22 : (z?: boolean | undefined) => string[] >bind(g21, "hello") : (z?: boolean | undefined) => string[] >bind : (f: (x: T, ...rest: U) => V, x: T) => (...rest: U) => V diff --git a/tests/cases/conformance/types/rest/genericRestParameters1.ts b/tests/cases/conformance/types/rest/genericRestParameters1.ts index ede07b0d9ac58..9274acb1976f6 100644 --- a/tests/cases/conformance/types/rest/genericRestParameters1.ts +++ b/tests/cases/conformance/types/rest/genericRestParameters1.ts @@ -22,7 +22,7 @@ f1(42, ...t2); f1(42, "hello", ...t1); f1(42, "hello", true, ...t0); f1(ns[0], ns[1], true); -f1(...ns, true); // FIXME: Error, since ...ns is considered as string|number here +f1(...ns, true); f2(42, "hello", true); f2(t3[0], t3[1], t3[2]); @@ -31,7 +31,7 @@ f2(42, ...t2); f2(42, "hello", ...t1); f2(42, "hello", true, ...t0); f2(ns[0], ns[1], true); -f2(...ns, true); // FIXME: Error, since ...ns is considered as string|number here +f2(...ns, true); declare function f10(...args: T): T; @@ -43,13 +43,13 @@ const x14 = f10(...t3); // [number, string, boolean] const x15 = f10(42, ...t2); // [number, string, boolean] const x16 = f10(42, "hello", ...t1); // [number, string, boolean] const x17 = f10(42, "hello", true, ...t0); // [number, string, boolean] -const x18 = f10(...ns, true); // (string | number | boolean)[] +const x18 = f10(...ns, true); // [number, string, boolean] function g10(u: U, v: V) { let x1 = f10(...u); // U - let x2 = f10(...v); // V - let x3 = f10(1, ...u); // [number, ...string[]] - let x4 = f10(...u, ...v); // (string | number)[] + let x2 = f10(...v); // [V["0"], V["1"]] + let x3 = f10(1, ...u); // [number, ...U] + let x4 = f10(...u, ...v); // [...U, V["0"], V["1"]] } declare function f11(...args: T): T; @@ -62,13 +62,13 @@ const z14 = f11(...t3); // [number, string, boolean] const z15 = f11(42, ...t2); // [42, string, boolean] const z16 = f11(42, "hello", ...t1); // [42, "hello", boolean] const z17 = f11(42, "hello", true, ...t0); // [42, "hello", true] -const z18 = f11(...ns, true); // (string | number | true)[] +const z18 = f11(...ns, true); // [number, string, true] function g11(u: U, v: V) { let x1 = f11(...u); // U - let x2 = f11(...v); // V - let x3 = f11(1, ...u); // [1, ...string[]] - let x4 = f11(...u, ...v); // (string | number)[] + let x2 = f11(...v); // [V["0"], V["1"]] + let x3 = f11(1, ...u); // [1, ...U] + let x4 = f11(...u, ...v); // [...U, V["0"], V["1"]] } function call(f: (...args: T) => U, ...args: T) { @@ -85,7 +85,7 @@ declare function f16(a: A, b: B): A | B; let x20 = call((x, y) => x + y, 10, 20); // number let x21 = call((x, y) => x + y, 10, "hello"); // string let x22 = call(f15, "hello", 42); // string | number -let x23 = call(f16, "hello", 42); // unknown +let x23 = call(f16, "hello", 42); // string | number let x24 = call<[string, number], string | number>(f16, "hello", 42); // string | number let x30 = callr(sn, (x, y) => x + y); // string @@ -109,8 +109,8 @@ f23(); declare const g20: (x: number, y?: string, z?: boolean) => string[]; -const g21 = bind(g20, 42); // (y: string, z: boolean) => string[] -const g22 = bind(g21, "hello"); // (z: boolean) => string[] +const g21 = bind(g20, 42); // (y?: string, z?: boolean) => string[] +const g22 = bind(g21, "hello"); // (z?: boolean) => string[] const g23 = bind(g22, true); // () => string[] g20(42, "hello", true);