• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// @strict: true
2// @declaration: true
3
4// Variadics in tuple types
5
6type TV0<T extends unknown[]> = [string, ...T];
7type TV1<T extends unknown[]> = [string, ...T, number];
8type TV2<T extends unknown[]> = [string, ...T, number, ...T];
9type TV3<T extends unknown[]> = [string, ...T, ...number[], ...T];
10
11// Normalization
12
13type TN1 = TV1<[boolean, string]>;
14type TN2 = TV1<[]>;
15type TN3 = TV1<[boolean?]>;
16type TN4 = TV1<string[]>;
17type TN5 = TV1<[boolean] | [symbol, symbol]>;
18type TN6 = TV1<any>;
19type TN7 = TV1<never>;
20
21// Variadics in array literals
22
23function tup2<T extends unknown[], U extends unknown[]>(t: [...T], u: [...U]) {
24    return [1, ...t, 2, ...u, 3] as const;
25}
26
27const t2 = tup2(['hello'], [10, true]);
28
29function concat<T extends unknown[], U extends unknown[]>(t: [...T], u: [...U]): [...T, ...U] {
30    return [...t, ...u];
31}
32
33declare const sa: string[];
34
35const tc1 = concat([], []);
36const tc2 = concat(['hello'], [42]);
37const tc3 = concat([1, 2, 3], sa);
38const tc4 = concat(sa, [1, 2, 3]);  // Ideally would be [...string[], number, number, number]
39
40function concat2<T extends readonly unknown[], U extends readonly unknown[]>(t: T, u: U) {
41    return [...t, ...u];  // (T[number] | U[number])[]
42}
43
44const tc5 = concat2([1, 2, 3] as const, [4, 5, 6] as const);  // (1 | 2 | 3 | 4 | 5 | 6)[]
45
46// Spread arguments
47
48declare function foo1(a: number, b: string, c: boolean, ...d: number[]): void;
49
50function foo2(t1: [number, string], t2: [boolean], a1: number[]) {
51    foo1(1, 'abc', true, 42, 43, 44);
52    foo1(...t1, true, 42, 43, 44);
53    foo1(...t1, ...t2, 42, 43, 44);
54    foo1(...t1, ...t2, ...a1);
55    foo1(...t1);  // Error
56    foo1(...t1, 45);  // Error
57}
58
59declare function foo3<T extends unknown[]>(x: number, ...args: [...T, number]): T;
60
61function foo4<U extends unknown[]>(u: U) {
62    foo3(1, 2);
63    foo3(1, 'hello', true, 2);
64    foo3(1, ...u, 'hi', 2);
65    foo3(1);
66}
67
68// Contextual typing of array literals
69
70declare function ft1<T extends unknown[]>(t: T): T;
71declare function ft2<T extends unknown[]>(t: T): readonly [...T];
72declare function ft3<T extends unknown[]>(t: [...T]): T;
73declare function ft4<T extends unknown[]>(t: [...T]): readonly [...T];
74
75ft1(['hello', 42]);  // (string | number)[]
76ft2(['hello', 42]);  // readonly (string | number)[]
77ft3(['hello', 42]);  // [string, number]
78ft4(['hello', 42]);  // readonly [string, number]
79
80// Indexing variadic tuple types
81
82function f0<T extends unknown[]>(t: [string, ...T], n: number) {
83    const a = t[0];  // string
84    const b = t[1];  // [string, ...T][1]
85    const c = t[2];  // [string, ...T][2]
86    const d = t[n];  // [string, ...T][number]
87}
88
89function f1<T extends unknown[]>(t: [string, ...T, number], n: number) {
90    const a = t[0];  // string
91    const b = t[1];  // [string, ...T, number][1]
92    const c = t[2];  // [string, ...T, number][2]
93    const d = t[n];  // [string, ...T, number][number]
94}
95
96// Destructuring variadic tuple types
97
98function f2<T extends unknown[]>(t: [string, ...T]) {
99    let [...ax] = t;  // [string, ...T]
100    let [b1, ...bx] = t;  // string, [...T]
101    let [c1, c2, ...cx] = t;  // string, [string, ...T][1], T[number][]
102}
103
104function f3<T extends unknown[]>(t: [string, ...T, number]) {
105    let [...ax] = t;  // [string, ...T, number]
106    let [b1, ...bx] = t;  // string, [...T, number]
107    let [c1, c2, ...cx] = t;  // string, [string, ...T, number][1], (number | T[number])[]
108}
109
110// Mapped types applied to variadic tuple types
111
112type Arrayify<T> = { [P in keyof T]: T[P][] };
113
114type TM1<U extends unknown[]> = Arrayify<readonly [string, number?, ...U, ...boolean[]]>;  // [string[], (number | undefined)[]?, Arrayify<U>, ...boolean[][]]
115
116type TP1<T extends unknown[]> = Partial<[string, ...T, number]>;  // [string?, Partial<T>, number?]
117type TP2<T extends unknown[]> = Partial<[string, ...T, ...number[]]>;  // [string?, Partial<T>, ...(number | undefined)[]]
118
119// Reverse mapping through mapped type applied to variadic tuple type
120
121declare function fm1<T extends unknown[]>(t: Arrayify<[string, number, ...T]>): T;
122
123let tm1 = fm1([['abc'], [42], [true], ['def']]);  // [boolean, string]
124
125// Spread of readonly array-like infers mutable array-like
126
127declare function fx1<T extends unknown[]>(a: string, ...args: T): T;
128
129function gx1<U extends unknown[], V extends readonly unknown[]>(u: U, v: V) {
130    fx1('abc');  // []
131    fx1('abc', ...u);  // U
132    fx1('abc', ...v);  // [...V]
133    fx1<U>('abc', ...u);  // U
134    fx1<V>('abc', ...v);  // Error
135}
136
137declare function fx2<T extends readonly unknown[]>(a: string, ...args: T): T;
138
139function gx2<U extends unknown[], V extends readonly unknown[]>(u: U, v: V) {
140    fx2('abc');  // []
141    fx2('abc', ...u);  // U
142    fx2('abc', ...v);  // [...V]
143    fx2<U>('abc', ...u);  // U
144    fx2<V>('abc', ...v);  // V
145}
146
147// Relations involving variadic tuple types
148
149function f10<T extends string[], U extends T>(x: [string, ...unknown[]], y: [string, ...T], z: [string, ...U]) {
150    x = y;
151    x = z;
152    y = x;  // Error
153    y = z;
154    z = x;  // Error
155    z = y;  // Error
156}
157
158// For a generic type T, [...T] is assignable to T, T is assignable to readonly [...T], and T is assignable
159// to [...T] when T is constrained to a mutable array or tuple type.
160
161function f11<T extends unknown[]>(t: T, m: [...T], r: readonly [...T]) {
162    t = m;
163    t = r;  // Error
164    m = t;
165    m = r;  // Error
166    r = t;
167    r = m;
168}
169
170function f12<T extends readonly unknown[]>(t: T, m: [...T], r: readonly [...T]) {
171    t = m;
172    t = r;  // Error
173    m = t;  // Error
174    m = r;  // Error
175    r = t;
176    r = m;
177}
178
179function f13<T extends string[], U extends T>(t0: T, t1: [...T], t2: [...U]) {
180    t0 = t1;
181    t0 = t2;
182    t1 = t0;
183    t1 = t2;
184    t2 = t0;  // Error
185    t2 = t1;  // Error
186}
187
188function f14<T extends readonly string[], U extends T>(t0: T, t1: [...T], t2: [...U]) {
189    t0 = t1;
190    t0 = t2;
191    t1 = t0;  // Error
192    t1 = t2;
193    t2 = t0;  // Error
194    t2 = t1;  // Error
195}
196
197function f15<T extends string[], U extends T>(k0: keyof T, k1: keyof [...T], k2: keyof [...U], k3: keyof [1, 2, ...T]) {
198    k0 = 'length';
199    k1 = 'length';
200    k2 = 'length';
201    k0 = 'slice';
202    k1 = 'slice';
203    k2 = 'slice';
204    k3 = '0';
205    k3 = '1';
206    k3 = '2';  // Error
207}
208
209// Inference between variadic tuple types
210
211type First<T extends readonly unknown[]> =
212    T extends readonly [unknown, ...unknown[]] ? T[0] :
213    T[0] | undefined;
214
215type DropFirst<T extends readonly unknown[]> = T extends readonly [unknown?, ...infer U] ? U : [...T];
216
217type Last<T extends readonly unknown[]> =
218    T extends readonly [...unknown[], infer U] ? U :
219    T extends readonly [unknown, ...unknown[]] ? T[number] :
220    T[number] | undefined;
221
222type DropLast<T extends readonly unknown[]> = T extends readonly [...infer U, unknown] ? U : [...T];
223
224type T00 = First<[number, symbol, string]>;
225type T01 = First<[symbol, string]>;
226type T02 = First<[string]>;
227type T03 = First<[number, symbol, ...string[]]>;
228type T04 = First<[symbol, ...string[]]>;
229type T05 = First<[string?]>;
230type T06 = First<string[]>;
231type T07 = First<[]>;
232type T08 = First<any>;
233type T09 = First<never>;
234
235type T10 = DropFirst<[number, symbol, string]>;
236type T11 = DropFirst<[symbol, string]>;
237type T12 = DropFirst<[string]>;
238type T13 = DropFirst<[number, symbol, ...string[]]>;
239type T14 = DropFirst<[symbol, ...string[]]>;
240type T15 = DropFirst<[string?]>;
241type T16 = DropFirst<string[]>;
242type T17 = DropFirst<[]>;
243type T18 = DropFirst<any>;
244type T19 = DropFirst<never>;
245
246type T20 = Last<[number, symbol, string]>;
247type T21 = Last<[symbol, string]>;
248type T22 = Last<[string]>;
249type T23 = Last<[number, symbol, ...string[]]>;
250type T24 = Last<[symbol, ...string[]]>;
251type T25 = Last<[string?]>;
252type T26 = Last<string[]>;
253type T27 = Last<[]>;
254type T28 = Last<any>;
255type T29 = Last<never>;
256
257type T30 = DropLast<[number, symbol, string]>;
258type T31 = DropLast<[symbol, string]>;
259type T32 = DropLast<[string]>;
260type T33 = DropLast<[number, symbol, ...string[]]>;
261type T34 = DropLast<[symbol, ...string[]]>;
262type T35 = DropLast<[string?]>;
263type T36 = DropLast<string[]>;
264type T37 = DropLast<[]>;  // unknown[], maybe should be []
265type T38 = DropLast<any>;
266type T39 = DropLast<never>;
267
268type R00 = First<readonly [number, symbol, string]>;
269type R01 = First<readonly [symbol, string]>;
270type R02 = First<readonly [string]>;
271type R03 = First<readonly [number, symbol, ...string[]]>;
272type R04 = First<readonly [symbol, ...string[]]>;
273type R05 = First<readonly string[]>;
274type R06 = First<readonly []>;
275
276type R10 = DropFirst<readonly [number, symbol, string]>;
277type R11 = DropFirst<readonly [symbol, string]>;
278type R12 = DropFirst<readonly [string]>;
279type R13 = DropFirst<readonly [number, symbol, ...string[]]>;
280type R14 = DropFirst<readonly [symbol, ...string[]]>;
281type R15 = DropFirst<readonly string[]>;
282type R16 = DropFirst<readonly []>;
283
284type R20 = Last<readonly [number, symbol, string]>;
285type R21 = Last<readonly [symbol, string]>;
286type R22 = Last<readonly [string]>;
287type R23 = Last<readonly [number, symbol, ...string[]]>;
288type R24 = Last<readonly [symbol, ...string[]]>;
289type R25 = Last<readonly string[]>;
290type R26 = Last<readonly []>;
291
292type R30 = DropLast<readonly [number, symbol, string]>;
293type R31 = DropLast<readonly [symbol, string]>;
294type R32 = DropLast<readonly [string]>;
295type R33 = DropLast<readonly [number, symbol, ...string[]]>;
296type R34 = DropLast<readonly [symbol, ...string[]]>;
297type R35 = DropLast<readonly string[]>;
298type R36 = DropLast<readonly []>;
299
300// Inference to [...T, ...U] with implied arity for T
301
302function curry<T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, ...a: T) {
303    return (...b: U) => f(...a, ...b);
304}
305
306const fn1 = (a: number, b: string, c: boolean, d: string[]) => 0;
307
308const c0 = curry(fn1);  // (a: number, b: string, c: boolean, d: string[]) => number
309const c1 = curry(fn1, 1);  // (b: string, c: boolean, d: string[]) => number
310const c2 = curry(fn1, 1, 'abc');  // (c: boolean, d: string[]) => number
311const c3 = curry(fn1, 1, 'abc', true);  // (d: string[]) => number
312const c4 = curry(fn1, 1, 'abc', true, ['x', 'y']);  // () => number
313
314const fn2 = (x: number, b: boolean, ...args: string[]) => 0;
315
316const c10 = curry(fn2);  // (x: number, b: boolean, ...args: string[]) => number
317const c11 = curry(fn2, 1);  // (b: boolean, ...args: string[]) => number
318const c12 = curry(fn2, 1, true);  // (...args: string[]) => number
319const c13 = curry(fn2, 1, true, 'abc', 'def');  // (...args: string[]) => number
320
321const fn3 = (...args: string[]) => 0;
322
323const c20 = curry(fn3);  // (...args: string[]) => number
324const c21 = curry(fn3, 'abc', 'def');  // (...args: string[]) => number
325const c22 = curry(fn3, ...sa);  // (...args: string[]) => number
326
327// No inference to [...T, ...U] when there is no implied arity
328
329function curry2<T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, t: [...T], u: [...U]) {
330    return f(...t, ...u);
331}
332
333declare function fn10(a: string, b: number, c: boolean): string[];
334
335curry2(fn10, ['hello', 42], [true]);
336curry2(fn10, ['hello'], [42, true]);
337
338// Inference to [...T] has higher priority than inference to [...T, number?]
339
340declare function ft<T extends unknown[]>(t1: [...T], t2: [...T, number?]): T;
341
342ft([1, 2, 3], [1, 2, 3]);
343ft([1, 2], [1, 2, 3]);
344ft(['a', 'b'], ['c', 'd'])
345ft(['a', 'b'], ['c', 'd', 42])
346
347// Last argument is contextually typed
348
349declare function call<T extends unknown[], R>(...args: [...T, (...args: T) => R]): [T, R];
350
351call('hello', 32, (a, b) => 42);
352call(...sa, (...x) => 42);
353
354// No inference to ending optional elements (except with identical structure)
355
356declare function f20<T extends unknown[] = []>(args: [...T, number?]): T;
357
358function f21<U extends string[]>(args: [...U, number?]) {
359    let v1 = f20(args);  // U
360    let v2 = f20(["foo", "bar"]);  // [string]
361    let v3 = f20(["foo", 42]);  // [string]
362}
363
364declare function f22<T extends unknown[] = []>(args: [...T, number]): T;
365declare function f22<T extends unknown[] = []>(args: [...T]): T;
366
367function f23<U extends string[]>(args: [...U, number]) {
368    let v1 = f22(args);  // U
369    let v2 = f22(["foo", "bar"]);  // [string, string]
370    let v3 = f22(["foo", 42]);  // [string]
371}
372
373// Repro from #39327
374
375interface Desc<A extends unknown[], T> {
376    readonly f: (...args: A) => T;
377    bind<T extends unknown[], U extends unknown[], R>(this: Desc<[...T, ...U], R>, ...args: T): Desc<[...U], R>;
378}
379
380declare const a: Desc<[string, number, boolean], object>;
381const b = a.bind("", 1);  // Desc<[boolean], object>
382
383// Repro from #39607
384
385declare function getUser(id: string, options?: { x?: string }): string;
386
387declare function getOrgUser(id: string, orgId: number, options?: { y?: number, z?: boolean }): void;
388
389function callApi<T extends unknown[] = [], U = void>(method: (...args: [...T, object]) => U) {
390    return (...args: [...T]) => method(...args, {});
391}
392
393callApi(getUser);
394callApi(getOrgUser);
395
396// Repro from #40235
397
398type Numbers = number[];
399type Unbounded = [...Numbers, boolean];
400const data: Unbounded = [false, false];  // Error
401
402type U1 = [string, ...Numbers, boolean];
403type U2 = [...[string, ...Numbers], boolean];
404type U3 = [...[string, number], boolean];
405