Skip to content

Commit d066e1e

Browse files
authored
Merge pull request #26676 from Microsoft/complexRestParameterTypes
Improve checking of complex rest parameter types
2 parents 0263027 + a2d2f5a commit d066e1e

9 files changed

+836
-186
lines changed

src/compiler/checker.ts

+101-97
Large diffs are not rendered by default.

tests/baselines/reference/destructuringParameterDeclaration4.errors.txt

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(13,13): error TS2370: A rest parameter must be of an array type.
21
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(14,17): error TS1047: A rest parameter cannot be optional.
32
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(15,16): error TS1048: A rest parameter cannot have an initializer.
43
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(20,19): error TS2345: Argument of type 'true' is not assignable to parameter of type 'string | number'.
@@ -16,7 +15,7 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(
1615
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(34,28): error TS2304: Cannot find name 'E'.
1716

1817

19-
==== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts (11 errors) ====
18+
==== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts (10 errors) ====
2019
// If the parameter is a rest parameter, the parameter type is any[]
2120
// A type annotation for a rest parameter must denote an array type.
2221

@@ -30,8 +29,6 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(
3029
function a0(...x: [number, number, string]) { } // Error, rest parameter must be array type
3130
function a1(...x: (number|string)[]) { }
3231
function a2(...a: someArray) { } // Error, rest parameter must be array type
33-
~~~~~~~~~~~~~~~
34-
!!! error TS2370: A rest parameter must be of an array type.
3532
function a3(...b?) { } // Error, can't be optional
3633
~
3734
!!! error TS1047: A rest parameter cannot be optional.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
tests/cases/conformance/types/rest/genericRestParameters3.ts(11,11): error TS2345: Argument of type '[10]' is not assignable to parameter of type '[string] | [number, boolean]'.
2+
Type '[10]' is not assignable to type '[string]'.
3+
Type '10' is not assignable to type 'string'.
4+
tests/cases/conformance/types/rest/genericRestParameters3.ts(12,1): error TS2345: Argument of type '[]' is not assignable to parameter of type '[string] | [number, boolean]'.
5+
Type '[]' is not assignable to type '[number, boolean]'.
6+
Property '0' is missing in type '[]'.
7+
tests/cases/conformance/types/rest/genericRestParameters3.ts(16,1): error TS2322: Type '(x: string, ...args: [string] | [number, boolean]) => void' is not assignable to type '(...args: [string, string] | [string, number, boolean]) => void'.
8+
tests/cases/conformance/types/rest/genericRestParameters3.ts(17,1): error TS2322: Type '(x: string, y: string) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
9+
Types of parameters 'y' and 'args' are incompatible.
10+
Type '[string] | [number, boolean]' is not assignable to type '[string]'.
11+
Type '[number, boolean]' is not assignable to type '[string]'.
12+
Types of property '0' are incompatible.
13+
Type 'number' is not assignable to type 'string'.
14+
tests/cases/conformance/types/rest/genericRestParameters3.ts(18,1): error TS2322: Type '(x: string, y: number, z: boolean) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
15+
Types of parameters 'y' and 'args' are incompatible.
16+
Type '[string] | [number, boolean]' is not assignable to type '[number, boolean]'.
17+
Type '[string]' is not assignable to type '[number, boolean]'.
18+
Property '1' is missing in type '[string]'.
19+
tests/cases/conformance/types/rest/genericRestParameters3.ts(19,1): error TS2322: Type '(...args: [string, string] | [string, number, boolean]) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
20+
tests/cases/conformance/types/rest/genericRestParameters3.ts(29,1): error TS2554: Expected 1 arguments, but got 0.
21+
tests/cases/conformance/types/rest/genericRestParameters3.ts(30,21): error TS2345: Argument of type '100' is not assignable to parameter of type '(...args: CoolArray<any>) => void'.
22+
tests/cases/conformance/types/rest/genericRestParameters3.ts(31,21): error TS2345: Argument of type '<T extends any[]>(cb: (...args: T) => void) => void' is not assignable to parameter of type '(...args: CoolArray<any>) => void'.
23+
Types of parameters 'cb' and 'args' are incompatible.
24+
Type 'CoolArray<any>' is not assignable to type '[(...args: any[]) => void]'.
25+
Property '0' is missing in type 'CoolArray<any>'.
26+
tests/cases/conformance/types/rest/genericRestParameters3.ts(38,32): error TS2345: Argument of type '[10, 20]' is not assignable to parameter of type 'CoolArray<number>'.
27+
Property 'hello' is missing in type '[10, 20]'.
28+
tests/cases/conformance/types/rest/genericRestParameters3.ts(43,1): error TS2345: Argument of type '[]' is not assignable to parameter of type 'CoolArray<never>'.
29+
Property 'hello' is missing in type '[]'.
30+
tests/cases/conformance/types/rest/genericRestParameters3.ts(44,5): error TS2345: Argument of type '[number]' is not assignable to parameter of type 'CoolArray<{}>'.
31+
Property 'hello' is missing in type '[number]'.
32+
tests/cases/conformance/types/rest/genericRestParameters3.ts(45,5): error TS2345: Argument of type '[number, number]' is not assignable to parameter of type 'CoolArray<{}>'.
33+
Property 'hello' is missing in type '[number, number]'.
34+
tests/cases/conformance/types/rest/genericRestParameters3.ts(46,5): error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'CoolArray<number>'.
35+
Property 'hello' is missing in type 'number[]'.
36+
tests/cases/conformance/types/rest/genericRestParameters3.ts(53,5): error TS2345: Argument of type '["what"]' is not assignable to parameter of type '[] | [number, string]'.
37+
Type '["what"]' is not assignable to type '[number, string]'.
38+
Property '1' is missing in type '["what"]'.
39+
40+
41+
==== tests/cases/conformance/types/rest/genericRestParameters3.ts (15 errors) ====
42+
declare let f1: (x: string, ...args: [string] | [number, boolean]) => void;
43+
declare let f2: (x: string, y: string) => void;
44+
declare let f3: (x: string, y: number, z: boolean) => void;
45+
declare let f4: (...args: [string, string] | [string, number, boolean]) => void;
46+
47+
declare const tt: [string] | [number, boolean];
48+
49+
f1("foo", "abc");
50+
f1("foo", 10, true);
51+
f1("foo", ...tt);
52+
f1("foo", 10); // Error
53+
~~
54+
!!! error TS2345: Argument of type '[10]' is not assignable to parameter of type '[string] | [number, boolean]'.
55+
!!! error TS2345: Type '[10]' is not assignable to type '[string]'.
56+
!!! error TS2345: Type '10' is not assignable to type 'string'.
57+
f1("foo"); // Error
58+
~~~~~~~~~
59+
!!! error TS2345: Argument of type '[]' is not assignable to parameter of type '[string] | [number, boolean]'.
60+
!!! error TS2345: Type '[]' is not assignable to type '[number, boolean]'.
61+
!!! error TS2345: Property '0' is missing in type '[]'.
62+
63+
f2 = f1;
64+
f3 = f1;
65+
f4 = f1; // Error, misaligned complex rest types
66+
~~
67+
!!! error TS2322: Type '(x: string, ...args: [string] | [number, boolean]) => void' is not assignable to type '(...args: [string, string] | [string, number, boolean]) => void'.
68+
f1 = f2; // Error
69+
~~
70+
!!! error TS2322: Type '(x: string, y: string) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
71+
!!! error TS2322: Types of parameters 'y' and 'args' are incompatible.
72+
!!! error TS2322: Type '[string] | [number, boolean]' is not assignable to type '[string]'.
73+
!!! error TS2322: Type '[number, boolean]' is not assignable to type '[string]'.
74+
!!! error TS2322: Types of property '0' are incompatible.
75+
!!! error TS2322: Type 'number' is not assignable to type 'string'.
76+
f1 = f3; // Error
77+
~~
78+
!!! error TS2322: Type '(x: string, y: number, z: boolean) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
79+
!!! error TS2322: Types of parameters 'y' and 'args' are incompatible.
80+
!!! error TS2322: Type '[string] | [number, boolean]' is not assignable to type '[number, boolean]'.
81+
!!! error TS2322: Type '[string]' is not assignable to type '[number, boolean]'.
82+
!!! error TS2322: Property '1' is missing in type '[string]'.
83+
f1 = f4; // Error, misaligned complex rest types
84+
~~
85+
!!! error TS2322: Type '(...args: [string, string] | [string, number, boolean]) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
86+
87+
// Repro from #26110
88+
89+
interface CoolArray<E> extends Array<E> {
90+
hello: number;
91+
}
92+
93+
declare function foo<T extends any[]>(cb: (...args: T) => void): void;
94+
95+
foo<CoolArray<any>>(); // Error
96+
~~~~~~~~~~~~~~~~~~~~~
97+
!!! error TS2554: Expected 1 arguments, but got 0.
98+
foo<CoolArray<any>>(100); // Error
99+
~~~
100+
!!! error TS2345: Argument of type '100' is not assignable to parameter of type '(...args: CoolArray<any>) => void'.
101+
foo<CoolArray<any>>(foo); // Error
102+
~~~
103+
!!! error TS2345: Argument of type '<T extends any[]>(cb: (...args: T) => void) => void' is not assignable to parameter of type '(...args: CoolArray<any>) => void'.
104+
!!! error TS2345: Types of parameters 'cb' and 'args' are incompatible.
105+
!!! error TS2345: Type 'CoolArray<any>' is not assignable to type '[(...args: any[]) => void]'.
106+
!!! error TS2345: Property '0' is missing in type 'CoolArray<any>'.
107+
108+
function bar<T extends any[]>(...args: T): T {
109+
return args;
110+
}
111+
112+
let a = bar(10, 20);
113+
let b = bar<CoolArray<number>>(10, 20); // Error
114+
~~
115+
!!! error TS2345: Argument of type '[10, 20]' is not assignable to parameter of type 'CoolArray<number>'.
116+
!!! error TS2345: Property 'hello' is missing in type '[10, 20]'.
117+
118+
declare function baz<T>(...args: CoolArray<T>): void;
119+
declare const ca: CoolArray<number>;
120+
121+
baz(); // Error
122+
~~~~~
123+
!!! error TS2345: Argument of type '[]' is not assignable to parameter of type 'CoolArray<never>'.
124+
!!! error TS2345: Property 'hello' is missing in type '[]'.
125+
baz(1); // Error
126+
~
127+
!!! error TS2345: Argument of type '[number]' is not assignable to parameter of type 'CoolArray<{}>'.
128+
!!! error TS2345: Property 'hello' is missing in type '[number]'.
129+
baz(1, 2); // Error
130+
~
131+
!!! error TS2345: Argument of type '[number, number]' is not assignable to parameter of type 'CoolArray<{}>'.
132+
!!! error TS2345: Property 'hello' is missing in type '[number, number]'.
133+
baz(...ca); // Error
134+
~~~~~
135+
!!! error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'CoolArray<number>'.
136+
!!! error TS2345: Property 'hello' is missing in type 'number[]'.
137+
138+
// Repro from #26491
139+
140+
declare function hmm<A extends [] | [number, string]>(...args: A): void;
141+
hmm(); // okay, A = []
142+
hmm(1, "s"); // okay, A = [1, "s"]
143+
hmm("what"); // no error? A = [] | [number, string] ?
144+
~~~~~~
145+
!!! error TS2345: Argument of type '["what"]' is not assignable to parameter of type '[] | [number, string]'.
146+
!!! error TS2345: Type '["what"]' is not assignable to type '[number, string]'.
147+
!!! error TS2345: Property '1' is missing in type '["what"]'.
148+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//// [genericRestParameters3.ts]
2+
declare let f1: (x: string, ...args: [string] | [number, boolean]) => void;
3+
declare let f2: (x: string, y: string) => void;
4+
declare let f3: (x: string, y: number, z: boolean) => void;
5+
declare let f4: (...args: [string, string] | [string, number, boolean]) => void;
6+
7+
declare const tt: [string] | [number, boolean];
8+
9+
f1("foo", "abc");
10+
f1("foo", 10, true);
11+
f1("foo", ...tt);
12+
f1("foo", 10); // Error
13+
f1("foo"); // Error
14+
15+
f2 = f1;
16+
f3 = f1;
17+
f4 = f1; // Error, misaligned complex rest types
18+
f1 = f2; // Error
19+
f1 = f3; // Error
20+
f1 = f4; // Error, misaligned complex rest types
21+
22+
// Repro from #26110
23+
24+
interface CoolArray<E> extends Array<E> {
25+
hello: number;
26+
}
27+
28+
declare function foo<T extends any[]>(cb: (...args: T) => void): void;
29+
30+
foo<CoolArray<any>>(); // Error
31+
foo<CoolArray<any>>(100); // Error
32+
foo<CoolArray<any>>(foo); // Error
33+
34+
function bar<T extends any[]>(...args: T): T {
35+
return args;
36+
}
37+
38+
let a = bar(10, 20);
39+
let b = bar<CoolArray<number>>(10, 20); // Error
40+
41+
declare function baz<T>(...args: CoolArray<T>): void;
42+
declare const ca: CoolArray<number>;
43+
44+
baz(); // Error
45+
baz(1); // Error
46+
baz(1, 2); // Error
47+
baz(...ca); // Error
48+
49+
// Repro from #26491
50+
51+
declare function hmm<A extends [] | [number, string]>(...args: A): void;
52+
hmm(); // okay, A = []
53+
hmm(1, "s"); // okay, A = [1, "s"]
54+
hmm("what"); // no error? A = [] | [number, string] ?
55+
56+
57+
//// [genericRestParameters3.js]
58+
"use strict";
59+
f1("foo", "abc");
60+
f1("foo", 10, true);
61+
f1.apply(void 0, ["foo"].concat(tt));
62+
f1("foo", 10); // Error
63+
f1("foo"); // Error
64+
f2 = f1;
65+
f3 = f1;
66+
f4 = f1; // Error, misaligned complex rest types
67+
f1 = f2; // Error
68+
f1 = f3; // Error
69+
f1 = f4; // Error, misaligned complex rest types
70+
foo(); // Error
71+
foo(100); // Error
72+
foo(foo); // Error
73+
function bar() {
74+
var args = [];
75+
for (var _i = 0; _i < arguments.length; _i++) {
76+
args[_i] = arguments[_i];
77+
}
78+
return args;
79+
}
80+
var a = bar(10, 20);
81+
var b = bar(10, 20); // Error
82+
baz(); // Error
83+
baz(1); // Error
84+
baz(1, 2); // Error
85+
baz.apply(void 0, ca); // Error
86+
hmm(); // okay, A = []
87+
hmm(1, "s"); // okay, A = [1, "s"]
88+
hmm("what"); // no error? A = [] | [number, string] ?
89+
90+
91+
//// [genericRestParameters3.d.ts]
92+
declare let f1: (x: string, ...args: [string] | [number, boolean]) => void;
93+
declare let f2: (x: string, y: string) => void;
94+
declare let f3: (x: string, y: number, z: boolean) => void;
95+
declare let f4: (...args: [string, string] | [string, number, boolean]) => void;
96+
declare const tt: [string] | [number, boolean];
97+
interface CoolArray<E> extends Array<E> {
98+
hello: number;
99+
}
100+
declare function foo<T extends any[]>(cb: (...args: T) => void): void;
101+
declare function bar<T extends any[]>(...args: T): T;
102+
declare let a: [number, number];
103+
declare let b: any;
104+
declare function baz<T>(...args: CoolArray<T>): void;
105+
declare const ca: CoolArray<number>;
106+
declare function hmm<A extends [] | [number, string]>(...args: A): void;

0 commit comments

Comments
 (0)