TypeScript/tests/baselines/reference/variadicTuples1.types

1413 lines
38 KiB
Plaintext

=== tests/cases/conformance/types/tuple/variadicTuples1.ts ===
// Variadics in tuple types
type TV0<T extends unknown[]> = [string, ...T];
>TV0 : [string, ...T]
type TV1<T extends unknown[]> = [string, ...T, number];
>TV1 : [string, ...T, number]
type TV2<T extends unknown[]> = [string, ...T, number, ...T];
>TV2 : [string, ...T, number, ...T]
type TV3<T extends unknown[]> = [string, ...T, ...number[], ...T];
>TV3 : [string, ...T, ...number[], ...T]
// Normalization
type TN1 = TV1<[boolean, string]>;
>TN1 : [string, boolean, string, number]
type TN2 = TV1<[]>;
>TN2 : [string, number]
type TN3 = TV1<[boolean?]>;
>TN3 : [string, boolean | undefined, number]
type TN4 = TV1<string[]>;
>TN4 : [string, ...string[], number]
type TN5 = TV1<[boolean] | [symbol, symbol]>;
>TN5 : [string, boolean, number] | [string, symbol, symbol, number]
type TN6 = TV1<any>;
>TN6 : [string, ...any[], number]
type TN7 = TV1<never>;
>TN7 : never
// Variadics in array literals
function tup2<T extends unknown[], U extends unknown[]>(t: [...T], u: [...U]) {
>tup2 : <T extends unknown[], U extends unknown[]>(t: [...T], u: [...U]) => readonly [1, ...T, 2, ...U, 3]
>t : [...T]
>u : [...U]
return [1, ...t, 2, ...u, 3] as const;
>[1, ...t, 2, ...u, 3] as const : readonly [1, ...T, 2, ...U, 3]
>[1, ...t, 2, ...u, 3] : readonly [1, ...T, 2, ...U, 3]
>1 : 1
>...t : T[number]
>t : [...T]
>2 : 2
>...u : U[number]
>u : [...U]
>3 : 3
}
const t2 = tup2(['hello'], [10, true]);
>t2 : readonly [1, string, 2, number, boolean, 3]
>tup2(['hello'], [10, true]) : readonly [1, string, 2, number, boolean, 3]
>tup2 : <T extends unknown[], U extends unknown[]>(t: [...T], u: [...U]) => readonly [1, ...T, 2, ...U, 3]
>['hello'] : [string]
>'hello' : "hello"
>[10, true] : [number, true]
>10 : 10
>true : true
function concat<T extends unknown[], U extends unknown[]>(t: [...T], u: [...U]): [...T, ...U] {
>concat : <T extends unknown[], U extends unknown[]>(t: [...T], u: [...U]) => [...T, ...U]
>t : [...T]
>u : [...U]
return [...t, ...u];
>[...t, ...u] : [...T, ...U]
>...t : T[number]
>t : [...T]
>...u : U[number]
>u : [...U]
}
declare const sa: string[];
>sa : string[]
const tc1 = concat([], []);
>tc1 : []
>concat([], []) : []
>concat : <T extends unknown[], U extends unknown[]>(t: [...T], u: [...U]) => [...T, ...U]
>[] : []
>[] : []
const tc2 = concat(['hello'], [42]);
>tc2 : [string, number]
>concat(['hello'], [42]) : [string, number]
>concat : <T extends unknown[], U extends unknown[]>(t: [...T], u: [...U]) => [...T, ...U]
>['hello'] : [string]
>'hello' : "hello"
>[42] : [number]
>42 : 42
const tc3 = concat([1, 2, 3], sa);
>tc3 : [number, number, number, ...string[]]
>concat([1, 2, 3], sa) : [number, number, number, ...string[]]
>concat : <T extends unknown[], U extends unknown[]>(t: [...T], u: [...U]) => [...T, ...U]
>[1, 2, 3] : [number, number, number]
>1 : 1
>2 : 2
>3 : 3
>sa : string[]
const tc4 = concat(sa, [1, 2, 3]); // Ideally would be [...string[], number, number, number]
>tc4 : [...string[], number, number, number]
>concat(sa, [1, 2, 3]) : [...string[], number, number, number]
>concat : <T extends unknown[], U extends unknown[]>(t: [...T], u: [...U]) => [...T, ...U]
>sa : string[]
>[1, 2, 3] : [number, number, number]
>1 : 1
>2 : 2
>3 : 3
function concat2<T extends readonly unknown[], U extends readonly unknown[]>(t: T, u: U) {
>concat2 : <T extends readonly unknown[], U extends readonly unknown[]>(t: T, u: U) => (T[number] | U[number])[]
>t : T
>u : U
return [...t, ...u]; // (T[number] | U[number])[]
>[...t, ...u] : (T[number] | U[number])[]
>...t : unknown
>t : T
>...u : unknown
>u : U
}
const tc5 = concat2([1, 2, 3] as const, [4, 5, 6] as const); // (1 | 2 | 3 | 4 | 5 | 6)[]
>tc5 : (2 | 4 | 1 | 3 | 6 | 5)[]
>concat2([1, 2, 3] as const, [4, 5, 6] as const) : (2 | 4 | 1 | 3 | 6 | 5)[]
>concat2 : <T extends readonly unknown[], U extends readonly unknown[]>(t: T, u: U) => (T[number] | U[number])[]
>[1, 2, 3] as const : readonly [1, 2, 3]
>[1, 2, 3] : readonly [1, 2, 3]
>1 : 1
>2 : 2
>3 : 3
>[4, 5, 6] as const : readonly [4, 5, 6]
>[4, 5, 6] : readonly [4, 5, 6]
>4 : 4
>5 : 5
>6 : 6
// Spread arguments
declare function foo1(a: number, b: string, c: boolean, ...d: number[]): void;
>foo1 : (a: number, b: string, c: boolean, ...d: number[]) => void
>a : number
>b : string
>c : boolean
>d : number[]
function foo2(t1: [number, string], t2: [boolean], a1: number[]) {
>foo2 : (t1: [number, string], t2: [boolean], a1: number[]) => void
>t1 : [number, string]
>t2 : [boolean]
>a1 : number[]
foo1(1, 'abc', true, 42, 43, 44);
>foo1(1, 'abc', true, 42, 43, 44) : void
>foo1 : (a: number, b: string, c: boolean, ...d: number[]) => void
>1 : 1
>'abc' : "abc"
>true : true
>42 : 42
>43 : 43
>44 : 44
foo1(...t1, true, 42, 43, 44);
>foo1(...t1, true, 42, 43, 44) : void
>foo1 : (a: number, b: string, c: boolean, ...d: number[]) => void
>...t1 : string | number
>t1 : [number, string]
>true : true
>42 : 42
>43 : 43
>44 : 44
foo1(...t1, ...t2, 42, 43, 44);
>foo1(...t1, ...t2, 42, 43, 44) : void
>foo1 : (a: number, b: string, c: boolean, ...d: number[]) => void
>...t1 : string | number
>t1 : [number, string]
>...t2 : boolean
>t2 : [boolean]
>42 : 42
>43 : 43
>44 : 44
foo1(...t1, ...t2, ...a1);
>foo1(...t1, ...t2, ...a1) : void
>foo1 : (a: number, b: string, c: boolean, ...d: number[]) => void
>...t1 : string | number
>t1 : [number, string]
>...t2 : boolean
>t2 : [boolean]
>...a1 : number
>a1 : number[]
foo1(...t1); // Error
>foo1(...t1) : void
>foo1 : (a: number, b: string, c: boolean, ...d: number[]) => void
>...t1 : string | number
>t1 : [number, string]
foo1(...t1, 45); // Error
>foo1(...t1, 45) : void
>foo1 : (a: number, b: string, c: boolean, ...d: number[]) => void
>...t1 : string | number
>t1 : [number, string]
>45 : 45
}
declare function foo3<T extends unknown[]>(x: number, ...args: [...T, number]): T;
>foo3 : <T extends unknown[]>(x: number, ...args: [...T, number]) => T
>x : number
>args : [...T, number]
function foo4<U extends unknown[]>(u: U) {
>foo4 : <U extends unknown[]>(u: U) => void
>u : U
foo3(1, 2);
>foo3(1, 2) : []
>foo3 : <T extends unknown[]>(x: number, ...args: [...T, number]) => T
>1 : 1
>2 : 2
foo3(1, 'hello', true, 2);
>foo3(1, 'hello', true, 2) : [string, boolean]
>foo3 : <T extends unknown[]>(x: number, ...args: [...T, number]) => T
>1 : 1
>'hello' : "hello"
>true : true
>2 : 2
foo3(1, ...u, 'hi', 2);
>foo3(1, ...u, 'hi', 2) : [...U, string]
>foo3 : <T extends unknown[]>(x: number, ...args: [...T, number]) => T
>1 : 1
>...u : unknown
>u : U
>'hi' : "hi"
>2 : 2
foo3(1);
>foo3(1) : unknown[]
>foo3 : <T extends unknown[]>(x: number, ...args: [...T, number]) => T
>1 : 1
}
// Contextual typing of array literals
declare function ft1<T extends unknown[]>(t: T): T;
>ft1 : <T extends unknown[]>(t: T) => T
>t : T
declare function ft2<T extends unknown[]>(t: T): readonly [...T];
>ft2 : <T extends unknown[]>(t: T) => readonly [...T]
>t : T
declare function ft3<T extends unknown[]>(t: [...T]): T;
>ft3 : <T extends unknown[]>(t: [...T]) => T
>t : [...T]
declare function ft4<T extends unknown[]>(t: [...T]): readonly [...T];
>ft4 : <T extends unknown[]>(t: [...T]) => readonly [...T]
>t : [...T]
ft1(['hello', 42]); // (string | number)[]
>ft1(['hello', 42]) : (string | number)[]
>ft1 : <T extends unknown[]>(t: T) => T
>['hello', 42] : (string | number)[]
>'hello' : "hello"
>42 : 42
ft2(['hello', 42]); // readonly (string | number)[]
>ft2(['hello', 42]) : readonly (string | number)[]
>ft2 : <T extends unknown[]>(t: T) => readonly [...T]
>['hello', 42] : (string | number)[]
>'hello' : "hello"
>42 : 42
ft3(['hello', 42]); // [string, number]
>ft3(['hello', 42]) : [string, number]
>ft3 : <T extends unknown[]>(t: [...T]) => T
>['hello', 42] : [string, number]
>'hello' : "hello"
>42 : 42
ft4(['hello', 42]); // readonly [string, number]
>ft4(['hello', 42]) : readonly [string, number]
>ft4 : <T extends unknown[]>(t: [...T]) => readonly [...T]
>['hello', 42] : [string, number]
>'hello' : "hello"
>42 : 42
// Indexing variadic tuple types
function f0<T extends unknown[]>(t: [string, ...T], n: number) {
>f0 : <T extends unknown[]>(t: [string, ...T], n: number) => void
>t : [string, ...T]
>n : number
const a = t[0]; // string
>a : string
>t[0] : string
>t : [string, ...T]
>0 : 0
const b = t[1]; // [string, ...T][1]
>b : [string, ...T][1]
>t[1] : [string, ...T][1]
>t : [string, ...T]
>1 : 1
const c = t[2]; // [string, ...T][2]
>c : [string, ...T][2]
>t[2] : [string, ...T][2]
>t : [string, ...T]
>2 : 2
const d = t[n]; // [string, ...T][number]
>d : [string, ...T][number]
>t[n] : [string, ...T][number]
>t : [string, ...T]
>n : number
}
function f1<T extends unknown[]>(t: [string, ...T, number], n: number) {
>f1 : <T extends unknown[]>(t: [string, ...T, number], n: number) => void
>t : [string, ...T, number]
>n : number
const a = t[0]; // string
>a : string
>t[0] : string
>t : [string, ...T, number]
>0 : 0
const b = t[1]; // [string, ...T, number][1]
>b : [string, ...T, number][1]
>t[1] : [string, ...T, number][1]
>t : [string, ...T, number]
>1 : 1
const c = t[2]; // [string, ...T, number][2]
>c : [string, ...T, number][2]
>t[2] : [string, ...T, number][2]
>t : [string, ...T, number]
>2 : 2
const d = t[n]; // [string, ...T, number][number]
>d : [string, ...T, number][number]
>t[n] : [string, ...T, number][number]
>t : [string, ...T, number]
>n : number
}
// Destructuring variadic tuple types
function f2<T extends unknown[]>(t: [string, ...T]) {
>f2 : <T extends unknown[]>(t: [string, ...T]) => void
>t : [string, ...T]
let [...ax] = t; // [string, ...T]
>ax : [string, ...T]
>t : [string, ...T]
let [b1, ...bx] = t; // string, [...T]
>b1 : string
>bx : [...T]
>t : [string, ...T]
let [c1, c2, ...cx] = t; // string, [string, ...T][1], T[number][]
>c1 : string
>c2 : [string, ...T][1]
>cx : T[number][]
>t : [string, ...T]
}
function f3<T extends unknown[]>(t: [string, ...T, number]) {
>f3 : <T extends unknown[]>(t: [string, ...T, number]) => void
>t : [string, ...T, number]
let [...ax] = t; // [string, ...T, number]
>ax : [string, ...T, number]
>t : [string, ...T, number]
let [b1, ...bx] = t; // string, [...T, number]
>b1 : string
>bx : [...T, number]
>t : [string, ...T, number]
let [c1, c2, ...cx] = t; // string, [string, ...T, number][1], (number | T[number])[]
>c1 : string
>c2 : [string, ...T, number][1]
>cx : (number | T[number])[]
>t : [string, ...T, number]
}
// Mapped types applied to variadic tuple types
type Arrayify<T> = { [P in keyof T]: T[P][] };
>Arrayify : Arrayify<T>
type TM1<U extends unknown[]> = Arrayify<readonly [string, number?, ...U, ...boolean[]]>; // [string[], (number | undefined)[]?, Arrayify<U>, ...boolean[][]]
>TM1 : readonly [string[], (number | undefined)[]?, ...Arrayify<U>, ...boolean[][]]
type TP1<T extends unknown[]> = Partial<[string, ...T, number]>; // [string?, Partial<T>, number?]
>TP1 : [(string | undefined)?, ...Partial<T>, (number | undefined)?]
type TP2<T extends unknown[]> = Partial<[string, ...T, ...number[]]>; // [string?, Partial<T>, ...(number | undefined)[]]
>TP2 : [(string | undefined)?, ...Partial<T>, ...(number | undefined)[]]
// Reverse mapping through mapped type applied to variadic tuple type
declare function fm1<T extends unknown[]>(t: Arrayify<[string, number, ...T]>): T;
>fm1 : <T extends unknown[]>(t: [string[], number[], ...Arrayify<T>]) => T
>t : [string[], number[], ...Arrayify<T>]
let tm1 = fm1([['abc'], [42], [true], ['def']]); // [boolean, string]
>tm1 : [boolean, string]
>fm1([['abc'], [42], [true], ['def']]) : [boolean, string]
>fm1 : <T extends unknown[]>(t: [string[], number[], ...Arrayify<T>]) => T
>[['abc'], [42], [true], ['def']] : [string[], number[], true[], string[]]
>['abc'] : string[]
>'abc' : "abc"
>[42] : number[]
>42 : 42
>[true] : true[]
>true : true
>['def'] : string[]
>'def' : "def"
// Spread of readonly array-like infers mutable array-like
declare function fx1<T extends unknown[]>(a: string, ...args: T): T;
>fx1 : <T extends unknown[]>(a: string, ...args: T) => T
>a : string
>args : T
function gx1<U extends unknown[], V extends readonly unknown[]>(u: U, v: V) {
>gx1 : <U extends unknown[], V extends readonly unknown[]>(u: U, v: V) => void
>u : U
>v : V
fx1('abc'); // []
>fx1('abc') : []
>fx1 : <T extends unknown[]>(a: string, ...args: T) => T
>'abc' : "abc"
fx1('abc', ...u); // U
>fx1('abc', ...u) : U
>fx1 : <T extends unknown[]>(a: string, ...args: T) => T
>'abc' : "abc"
>...u : unknown
>u : U
fx1('abc', ...v); // [...V]
>fx1('abc', ...v) : [...V]
>fx1 : <T extends unknown[]>(a: string, ...args: T) => T
>'abc' : "abc"
>...v : unknown
>v : V
fx1<U>('abc', ...u); // U
>fx1<U>('abc', ...u) : U
>fx1 : <T extends unknown[]>(a: string, ...args: T) => T
>'abc' : "abc"
>...u : unknown
>u : U
fx1<V>('abc', ...v); // Error
>fx1<V>('abc', ...v) : V
>fx1 : <T extends unknown[]>(a: string, ...args: T) => T
>'abc' : "abc"
>...v : unknown
>v : V
}
declare function fx2<T extends readonly unknown[]>(a: string, ...args: T): T;
>fx2 : <T extends readonly unknown[]>(a: string, ...args: T) => T
>a : string
>args : T
function gx2<U extends unknown[], V extends readonly unknown[]>(u: U, v: V) {
>gx2 : <U extends unknown[], V extends readonly unknown[]>(u: U, v: V) => void
>u : U
>v : V
fx2('abc'); // []
>fx2('abc') : []
>fx2 : <T extends readonly unknown[]>(a: string, ...args: T) => T
>'abc' : "abc"
fx2('abc', ...u); // U
>fx2('abc', ...u) : U
>fx2 : <T extends readonly unknown[]>(a: string, ...args: T) => T
>'abc' : "abc"
>...u : unknown
>u : U
fx2('abc', ...v); // [...V]
>fx2('abc', ...v) : [...V]
>fx2 : <T extends readonly unknown[]>(a: string, ...args: T) => T
>'abc' : "abc"
>...v : unknown
>v : V
fx2<U>('abc', ...u); // U
>fx2<U>('abc', ...u) : U
>fx2 : <T extends readonly unknown[]>(a: string, ...args: T) => T
>'abc' : "abc"
>...u : unknown
>u : U
fx2<V>('abc', ...v); // V
>fx2<V>('abc', ...v) : V
>fx2 : <T extends readonly unknown[]>(a: string, ...args: T) => T
>'abc' : "abc"
>...v : unknown
>v : V
}
// Relations involving variadic tuple types
function f10<T extends string[], U extends T>(x: [string, ...unknown[]], y: [string, ...T], z: [string, ...U]) {
>f10 : <T extends string[], U extends T>(x: [string, ...unknown[]], y: [string, ...T], z: [string, ...U]) => void
>x : [string, ...unknown[]]
>y : [string, ...T]
>z : [string, ...U]
x = y;
>x = y : [string, ...T]
>x : [string, ...unknown[]]
>y : [string, ...T]
x = z;
>x = z : [string, ...U]
>x : [string, ...unknown[]]
>z : [string, ...U]
y = x; // Error
>y = x : [string, ...unknown[]]
>y : [string, ...T]
>x : [string, ...unknown[]]
y = z;
>y = z : [string, ...U]
>y : [string, ...T]
>z : [string, ...U]
z = x; // Error
>z = x : [string, ...unknown[]]
>z : [string, ...U]
>x : [string, ...unknown[]]
z = y; // Error
>z = y : [string, ...T]
>z : [string, ...U]
>y : [string, ...T]
}
// For a generic type T, [...T] is assignable to T, T is assignable to readonly [...T], and T is assignable
// to [...T] when T is constrained to a mutable array or tuple type.
function f11<T extends unknown[]>(t: T, m: [...T], r: readonly [...T]) {
>f11 : <T extends unknown[]>(t: T, m: [...T], r: readonly [...T]) => void
>t : T
>m : [...T]
>r : readonly [...T]
t = m;
>t = m : [...T]
>t : T
>m : [...T]
t = r; // Error
>t = r : readonly [...T]
>t : T
>r : readonly [...T]
m = t;
>m = t : T
>m : [...T]
>t : T
m = r; // Error
>m = r : readonly [...T]
>m : [...T]
>r : readonly [...T]
r = t;
>r = t : T
>r : readonly [...T]
>t : T
r = m;
>r = m : [...T]
>r : readonly [...T]
>m : [...T]
}
function f12<T extends readonly unknown[]>(t: T, m: [...T], r: readonly [...T]) {
>f12 : <T extends readonly unknown[]>(t: T, m: [...T], r: readonly [...T]) => void
>t : T
>m : [...T]
>r : readonly [...T]
t = m;
>t = m : [...T]
>t : T
>m : [...T]
t = r; // Error
>t = r : readonly [...T]
>t : T
>r : readonly [...T]
m = t; // Error
>m = t : T
>m : [...T]
>t : T
m = r; // Error
>m = r : readonly [...T]
>m : [...T]
>r : readonly [...T]
r = t;
>r = t : T
>r : readonly [...T]
>t : T
r = m;
>r = m : [...T]
>r : readonly [...T]
>m : [...T]
}
function f13<T extends string[], U extends T>(t0: T, t1: [...T], t2: [...U]) {
>f13 : <T extends string[], U extends T>(t0: T, t1: [...T], t2: [...U]) => void
>t0 : T
>t1 : [...T]
>t2 : [...U]
t0 = t1;
>t0 = t1 : [...T]
>t0 : T
>t1 : [...T]
t0 = t2;
>t0 = t2 : [...U]
>t0 : T
>t2 : [...U]
t1 = t0;
>t1 = t0 : T
>t1 : [...T]
>t0 : T
t1 = t2;
>t1 = t2 : [...U]
>t1 : [...T]
>t2 : [...U]
t2 = t0; // Error
>t2 = t0 : T
>t2 : [...U]
>t0 : T
t2 = t1; // Error
>t2 = t1 : [...T]
>t2 : [...U]
>t1 : [...T]
}
function f14<T extends readonly string[], U extends T>(t0: T, t1: [...T], t2: [...U]) {
>f14 : <T extends readonly string[], U extends T>(t0: T, t1: [...T], t2: [...U]) => void
>t0 : T
>t1 : [...T]
>t2 : [...U]
t0 = t1;
>t0 = t1 : [...T]
>t0 : T
>t1 : [...T]
t0 = t2;
>t0 = t2 : [...U]
>t0 : T
>t2 : [...U]
t1 = t0; // Error
>t1 = t0 : T
>t1 : [...T]
>t0 : T
t1 = t2;
>t1 = t2 : [...U]
>t1 : [...T]
>t2 : [...U]
t2 = t0; // Error
>t2 = t0 : T
>t2 : [...U]
>t0 : T
t2 = t1; // Error
>t2 = t1 : [...T]
>t2 : [...U]
>t1 : [...T]
}
function f15<T extends string[], U extends T>(k0: keyof T, k1: keyof [...T], k2: keyof [...U], k3: keyof [1, 2, ...T]) {
>f15 : <T extends string[], U extends T>(k0: keyof T, k1: keyof [...T], k2: keyof [...U], k3: keyof [1, 2, ...T]) => void
>k0 : keyof T
>k1 : keyof [...T]
>k2 : keyof [...U]
>k3 : keyof [1, 2, ...T]
k0 = 'length';
>k0 = 'length' : "length"
>k0 : keyof T
>'length' : "length"
k1 = 'length';
>k1 = 'length' : "length"
>k1 : keyof [...T]
>'length' : "length"
k2 = 'length';
>k2 = 'length' : "length"
>k2 : keyof [...U]
>'length' : "length"
k0 = 'slice';
>k0 = 'slice' : "slice"
>k0 : keyof T
>'slice' : "slice"
k1 = 'slice';
>k1 = 'slice' : "slice"
>k1 : keyof [...T]
>'slice' : "slice"
k2 = 'slice';
>k2 = 'slice' : "slice"
>k2 : keyof [...U]
>'slice' : "slice"
k3 = '0';
>k3 = '0' : "0"
>k3 : keyof [1, 2, ...T]
>'0' : "0"
k3 = '1';
>k3 = '1' : "1"
>k3 : keyof [1, 2, ...T]
>'1' : "1"
k3 = '2'; // Error
>k3 = '2' : "2"
>k3 : keyof [1, 2, ...T]
>'2' : "2"
}
// Inference between variadic tuple types
type First<T extends readonly unknown[]> =
>First : First<T>
T extends readonly [unknown, ...unknown[]] ? T[0] :
T[0] | undefined;
type DropFirst<T extends readonly unknown[]> = T extends readonly [unknown?, ...infer U] ? U : [...T];
>DropFirst : DropFirst<T>
type Last<T extends readonly unknown[]> =
>Last : Last<T>
T extends readonly [...unknown[], infer U] ? U :
T extends readonly [unknown, ...unknown[]] ? T[number] :
T[number] | undefined;
type DropLast<T extends readonly unknown[]> = T extends readonly [...infer U, unknown] ? U : [...T];
>DropLast : DropLast<T>
type T00 = First<[number, symbol, string]>;
>T00 : number
type T01 = First<[symbol, string]>;
>T01 : symbol
type T02 = First<[string]>;
>T02 : string
type T03 = First<[number, symbol, ...string[]]>;
>T03 : number
type T04 = First<[symbol, ...string[]]>;
>T04 : symbol
type T05 = First<[string?]>;
>T05 : string | undefined
type T06 = First<string[]>;
>T06 : string | undefined
type T07 = First<[]>;
>T07 : undefined
type T08 = First<any>;
>T08 : any
type T09 = First<never>;
>T09 : never
type T10 = DropFirst<[number, symbol, string]>;
>T10 : [symbol, string]
type T11 = DropFirst<[symbol, string]>;
>T11 : [string]
type T12 = DropFirst<[string]>;
>T12 : []
type T13 = DropFirst<[number, symbol, ...string[]]>;
>T13 : [symbol, ...string[]]
type T14 = DropFirst<[symbol, ...string[]]>;
>T14 : string[]
type T15 = DropFirst<[string?]>;
>T15 : []
type T16 = DropFirst<string[]>;
>T16 : string[]
type T17 = DropFirst<[]>;
>T17 : unknown[]
type T18 = DropFirst<any>;
>T18 : unknown[] | any[]
type T19 = DropFirst<never>;
>T19 : never
type T20 = Last<[number, symbol, string]>;
>T20 : string
type T21 = Last<[symbol, string]>;
>T21 : string
type T22 = Last<[string]>;
>T22 : string
type T23 = Last<[number, symbol, ...string[]]>;
>T23 : string | number | symbol
type T24 = Last<[symbol, ...string[]]>;
>T24 : string | symbol
type T25 = Last<[string?]>;
>T25 : string | undefined
type T26 = Last<string[]>;
>T26 : string | undefined
type T27 = Last<[]>;
>T27 : undefined
type T28 = Last<any>;
>T28 : any
type T29 = Last<never>;
>T29 : never
type T30 = DropLast<[number, symbol, string]>;
>T30 : [number, symbol]
type T31 = DropLast<[symbol, string]>;
>T31 : [symbol]
type T32 = DropLast<[string]>;
>T32 : []
type T33 = DropLast<[number, symbol, ...string[]]>;
>T33 : [number, symbol, ...string[]]
type T34 = DropLast<[symbol, ...string[]]>;
>T34 : [symbol, ...string[]]
type T35 = DropLast<[string?]>;
>T35 : [(string | undefined)?]
type T36 = DropLast<string[]>;
>T36 : string[]
type T37 = DropLast<[]>; // unknown[], maybe should be []
>T37 : []
type T38 = DropLast<any>;
>T38 : unknown[] | any[]
type T39 = DropLast<never>;
>T39 : never
type R00 = First<readonly [number, symbol, string]>;
>R00 : number
type R01 = First<readonly [symbol, string]>;
>R01 : symbol
type R02 = First<readonly [string]>;
>R02 : string
type R03 = First<readonly [number, symbol, ...string[]]>;
>R03 : number
type R04 = First<readonly [symbol, ...string[]]>;
>R04 : symbol
type R05 = First<readonly string[]>;
>R05 : string | undefined
type R06 = First<readonly []>;
>R06 : undefined
type R10 = DropFirst<readonly [number, symbol, string]>;
>R10 : [symbol, string]
type R11 = DropFirst<readonly [symbol, string]>;
>R11 : [string]
type R12 = DropFirst<readonly [string]>;
>R12 : []
type R13 = DropFirst<readonly [number, symbol, ...string[]]>;
>R13 : [symbol, ...string[]]
type R14 = DropFirst<readonly [symbol, ...string[]]>;
>R14 : string[]
type R15 = DropFirst<readonly string[]>;
>R15 : string[]
type R16 = DropFirst<readonly []>;
>R16 : unknown[]
type R20 = Last<readonly [number, symbol, string]>;
>R20 : string
type R21 = Last<readonly [symbol, string]>;
>R21 : string
type R22 = Last<readonly [string]>;
>R22 : string
type R23 = Last<readonly [number, symbol, ...string[]]>;
>R23 : string | number | symbol
type R24 = Last<readonly [symbol, ...string[]]>;
>R24 : string | symbol
type R25 = Last<readonly string[]>;
>R25 : string | undefined
type R26 = Last<readonly []>;
>R26 : undefined
type R30 = DropLast<readonly [number, symbol, string]>;
>R30 : [number, symbol]
type R31 = DropLast<readonly [symbol, string]>;
>R31 : [symbol]
type R32 = DropLast<readonly [string]>;
>R32 : []
type R33 = DropLast<readonly [number, symbol, ...string[]]>;
>R33 : [number, symbol, ...string[]]
type R34 = DropLast<readonly [symbol, ...string[]]>;
>R34 : [symbol, ...string[]]
type R35 = DropLast<readonly string[]>;
>R35 : string[]
type R36 = DropLast<readonly []>;
>R36 : []
// Inference to [...T, ...U] with implied arity for T
function curry<T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, ...a: T) {
>curry : <T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, ...a: T) => (...b: U) => R
>f : (...args: [...T, ...U]) => R
>args : [...T, ...U]
>a : T
return (...b: U) => f(...a, ...b);
>(...b: U) => f(...a, ...b) : (...b: U) => R
>b : U
>f(...a, ...b) : R
>f : (...args: [...T, ...U]) => R
>...a : unknown
>a : T
>...b : unknown
>b : U
}
const fn1 = (a: number, b: string, c: boolean, d: string[]) => 0;
>fn1 : (a: number, b: string, c: boolean, d: string[]) => number
>(a: number, b: string, c: boolean, d: string[]) => 0 : (a: number, b: string, c: boolean, d: string[]) => number
>a : number
>b : string
>c : boolean
>d : string[]
>0 : 0
const c0 = curry(fn1); // (a: number, b: string, c: boolean, d: string[]) => number
>c0 : (a: number, b: string, c: boolean, d: string[]) => number
>curry(fn1) : (a: number, b: string, c: boolean, d: string[]) => number
>curry : <T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, ...a: T) => (...b: U) => R
>fn1 : (a: number, b: string, c: boolean, d: string[]) => number
const c1 = curry(fn1, 1); // (b: string, c: boolean, d: string[]) => number
>c1 : (b: string, c: boolean, d: string[]) => number
>curry(fn1, 1) : (b: string, c: boolean, d: string[]) => number
>curry : <T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, ...a: T) => (...b: U) => R
>fn1 : (a: number, b: string, c: boolean, d: string[]) => number
>1 : 1
const c2 = curry(fn1, 1, 'abc'); // (c: boolean, d: string[]) => number
>c2 : (c: boolean, d: string[]) => number
>curry(fn1, 1, 'abc') : (c: boolean, d: string[]) => number
>curry : <T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, ...a: T) => (...b: U) => R
>fn1 : (a: number, b: string, c: boolean, d: string[]) => number
>1 : 1
>'abc' : "abc"
const c3 = curry(fn1, 1, 'abc', true); // (d: string[]) => number
>c3 : (d: string[]) => number
>curry(fn1, 1, 'abc', true) : (d: string[]) => number
>curry : <T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, ...a: T) => (...b: U) => R
>fn1 : (a: number, b: string, c: boolean, d: string[]) => number
>1 : 1
>'abc' : "abc"
>true : true
const c4 = curry(fn1, 1, 'abc', true, ['x', 'y']); // () => number
>c4 : () => number
>curry(fn1, 1, 'abc', true, ['x', 'y']) : () => number
>curry : <T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, ...a: T) => (...b: U) => R
>fn1 : (a: number, b: string, c: boolean, d: string[]) => number
>1 : 1
>'abc' : "abc"
>true : true
>['x', 'y'] : string[]
>'x' : "x"
>'y' : "y"
const fn2 = (x: number, b: boolean, ...args: string[]) => 0;
>fn2 : (x: number, b: boolean, ...args: string[]) => number
>(x: number, b: boolean, ...args: string[]) => 0 : (x: number, b: boolean, ...args: string[]) => number
>x : number
>b : boolean
>args : string[]
>0 : 0
const c10 = curry(fn2); // (x: number, b: boolean, ...args: string[]) => number
>c10 : (x: number, b: boolean, ...args: string[]) => number
>curry(fn2) : (x: number, b: boolean, ...args: string[]) => number
>curry : <T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, ...a: T) => (...b: U) => R
>fn2 : (x: number, b: boolean, ...args: string[]) => number
const c11 = curry(fn2, 1); // (b: boolean, ...args: string[]) => number
>c11 : (b: boolean, ...args: string[]) => number
>curry(fn2, 1) : (b: boolean, ...args: string[]) => number
>curry : <T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, ...a: T) => (...b: U) => R
>fn2 : (x: number, b: boolean, ...args: string[]) => number
>1 : 1
const c12 = curry(fn2, 1, true); // (...args: string[]) => number
>c12 : (...b: string[]) => number
>curry(fn2, 1, true) : (...b: string[]) => number
>curry : <T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, ...a: T) => (...b: U) => R
>fn2 : (x: number, b: boolean, ...args: string[]) => number
>1 : 1
>true : true
const c13 = curry(fn2, 1, true, 'abc', 'def'); // (...args: string[]) => number
>c13 : (...b: string[]) => number
>curry(fn2, 1, true, 'abc', 'def') : (...b: string[]) => number
>curry : <T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, ...a: T) => (...b: U) => R
>fn2 : (x: number, b: boolean, ...args: string[]) => number
>1 : 1
>true : true
>'abc' : "abc"
>'def' : "def"
const fn3 = (...args: string[]) => 0;
>fn3 : (...args: string[]) => number
>(...args: string[]) => 0 : (...args: string[]) => number
>args : string[]
>0 : 0
const c20 = curry(fn3); // (...args: string[]) => number
>c20 : (...b: string[]) => number
>curry(fn3) : (...b: string[]) => number
>curry : <T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, ...a: T) => (...b: U) => R
>fn3 : (...args: string[]) => number
const c21 = curry(fn3, 'abc', 'def'); // (...args: string[]) => number
>c21 : (...b: string[]) => number
>curry(fn3, 'abc', 'def') : (...b: string[]) => number
>curry : <T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, ...a: T) => (...b: U) => R
>fn3 : (...args: string[]) => number
>'abc' : "abc"
>'def' : "def"
const c22 = curry(fn3, ...sa); // (...args: string[]) => number
>c22 : (...b: string[]) => number
>curry(fn3, ...sa) : (...b: string[]) => number
>curry : <T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, ...a: T) => (...b: U) => R
>fn3 : (...args: string[]) => number
>...sa : string
>sa : string[]
// No inference to [...T, ...U] when there is no implied arity
function curry2<T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, t: [...T], u: [...U]) {
>curry2 : <T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, t: [...T], u: [...U]) => R
>f : (...args: [...T, ...U]) => R
>args : [...T, ...U]
>t : [...T]
>u : [...U]
return f(...t, ...u);
>f(...t, ...u) : R
>f : (...args: [...T, ...U]) => R
>...t : T[number]
>t : [...T]
>...u : U[number]
>u : [...U]
}
declare function fn10(a: string, b: number, c: boolean): string[];
>fn10 : (a: string, b: number, c: boolean) => string[]
>a : string
>b : number
>c : boolean
curry2(fn10, ['hello', 42], [true]);
>curry2(fn10, ['hello', 42], [true]) : string[]
>curry2 : <T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, t: [...T], u: [...U]) => R
>fn10 : (a: string, b: number, c: boolean) => string[]
>['hello', 42] : [string, number]
>'hello' : "hello"
>42 : 42
>[true] : [true]
>true : true
curry2(fn10, ['hello'], [42, true]);
>curry2(fn10, ['hello'], [42, true]) : string[]
>curry2 : <T extends unknown[], U extends unknown[], R>(f: (...args: [...T, ...U]) => R, t: [...T], u: [...U]) => R
>fn10 : (a: string, b: number, c: boolean) => string[]
>['hello'] : [string]
>'hello' : "hello"
>[42, true] : [number, true]
>42 : 42
>true : true
// Inference to [...T] has higher priority than inference to [...T, number?]
declare function ft<T extends unknown[]>(t1: [...T], t2: [...T, number?]): T;
>ft : <T extends unknown[]>(t1: [...T], t2: [...T, number?]) => T
>t1 : [...T]
>t2 : [...T, (number | undefined)?]
ft([1, 2, 3], [1, 2, 3]);
>ft([1, 2, 3], [1, 2, 3]) : [number, number, number]
>ft : <T extends unknown[]>(t1: [...T], t2: [...T, (number | undefined)?]) => T
>[1, 2, 3] : [number, number, number]
>1 : 1
>2 : 2
>3 : 3
>[1, 2, 3] : [number, number, number]
>1 : 1
>2 : 2
>3 : 3
ft([1, 2], [1, 2, 3]);
>ft([1, 2], [1, 2, 3]) : [number, number]
>ft : <T extends unknown[]>(t1: [...T], t2: [...T, (number | undefined)?]) => T
>[1, 2] : [number, number]
>1 : 1
>2 : 2
>[1, 2, 3] : [number, number, number]
>1 : 1
>2 : 2
>3 : 3
ft(['a', 'b'], ['c', 'd'])
>ft(['a', 'b'], ['c', 'd']) : [string, string]
>ft : <T extends unknown[]>(t1: [...T], t2: [...T, (number | undefined)?]) => T
>['a', 'b'] : [string, string]
>'a' : "a"
>'b' : "b"
>['c', 'd'] : [string, string]
>'c' : "c"
>'d' : "d"
ft(['a', 'b'], ['c', 'd', 42])
>ft(['a', 'b'], ['c', 'd', 42]) : [string, string]
>ft : <T extends unknown[]>(t1: [...T], t2: [...T, (number | undefined)?]) => T
>['a', 'b'] : [string, string]
>'a' : "a"
>'b' : "b"
>['c', 'd', 42] : [string, string, number]
>'c' : "c"
>'d' : "d"
>42 : 42
// Last argument is contextually typed
declare function call<T extends unknown[], R>(...args: [...T, (...args: T) => R]): [T, R];
>call : <T extends unknown[], R>(...args: [...T, (...args: T) => R]) => [T, R]
>args : [...T, (...args: T) => R]
>args : T
call('hello', 32, (a, b) => 42);
>call('hello', 32, (a, b) => 42) : [[string, number], number]
>call : <T extends unknown[], R>(...args: [...T, (...args: T) => R]) => [T, R]
>'hello' : "hello"
>32 : 32
>(a, b) => 42 : (a: string, b: number) => number
>a : string
>b : number
>42 : 42
call(...sa, (...x) => 42);
>call(...sa, (...x) => 42) : [string[], number]
>call : <T extends unknown[], R>(...args: [...T, (...args: T) => R]) => [T, R]
>...sa : string
>sa : string[]
>(...x) => 42 : (...x: string[]) => number
>x : string[]
>42 : 42
// No inference to ending optional elements (except with identical structure)
declare function f20<T extends unknown[] = []>(args: [...T, number?]): T;
>f20 : <T extends unknown[] = []>(args: [...T, number?]) => T
>args : [...T, (number | undefined)?]
function f21<U extends string[]>(args: [...U, number?]) {
>f21 : <U extends string[]>(args: [...U, number?]) => void
>args : [...U, (number | undefined)?]
let v1 = f20(args); // U
>v1 : U
>f20(args) : U
>f20 : <T extends unknown[] = []>(args: [...T, (number | undefined)?]) => T
>args : [...U, (number | undefined)?]
let v2 = f20(["foo", "bar"]); // [string]
>v2 : [string]
>f20(["foo", "bar"]) : [string]
>f20 : <T extends unknown[] = []>(args: [...T, (number | undefined)?]) => T
>["foo", "bar"] : [string, string]
>"foo" : "foo"
>"bar" : "bar"
let v3 = f20(["foo", 42]); // [string]
>v3 : [string]
>f20(["foo", 42]) : [string]
>f20 : <T extends unknown[] = []>(args: [...T, (number | undefined)?]) => T
>["foo", 42] : [string, number]
>"foo" : "foo"
>42 : 42
}
declare function f22<T extends unknown[] = []>(args: [...T, number]): T;
>f22 : { <T extends unknown[] = []>(args: [...T, number]): T; <T extends unknown[] = []>(args: [...T]): T; }
>args : [...T, number]
declare function f22<T extends unknown[] = []>(args: [...T]): T;
>f22 : { <T extends unknown[] = []>(args: [...T, number]): T; <T extends unknown[] = []>(args: [...T]): T; }
>args : [...T]
function f23<U extends string[]>(args: [...U, number]) {
>f23 : <U extends string[]>(args: [...U, number]) => void
>args : [...U, number]
let v1 = f22(args); // U
>v1 : U
>f22(args) : U
>f22 : { <T extends unknown[] = []>(args: [...T, number]): T; <T extends unknown[] = []>(args: [...T]): T; }
>args : [...U, number]
let v2 = f22(["foo", "bar"]); // [string, string]
>v2 : [string, string]
>f22(["foo", "bar"]) : [string, string]
>f22 : { <T extends unknown[] = []>(args: [...T, number]): T; <T extends unknown[] = []>(args: [...T]): T; }
>["foo", "bar"] : [string, string]
>"foo" : "foo"
>"bar" : "bar"
let v3 = f22(["foo", 42]); // [string]
>v3 : [string]
>f22(["foo", 42]) : [string]
>f22 : { <T extends unknown[] = []>(args: [...T, number]): T; <T extends unknown[] = []>(args: [...T]): T; }
>["foo", 42] : [string, number]
>"foo" : "foo"
>42 : 42
}
// Repro from #39327
interface Desc<A extends unknown[], T> {
readonly f: (...args: A) => T;
>f : (...args: A) => T
>args : A
bind<T extends unknown[], U extends unknown[], R>(this: Desc<[...T, ...U], R>, ...args: T): Desc<[...U], R>;
>bind : <T extends unknown[], U extends unknown[], R>(this: Desc<[...T, ...U], R>, ...args: T) => Desc<[...U], R>
>this : Desc<[...T, ...U], R>
>args : T
}
declare const a: Desc<[string, number, boolean], object>;
>a : Desc<[string, number, boolean], object>
const b = a.bind("", 1); // Desc<[boolean], object>
>b : Desc<[boolean], object>
>a.bind("", 1) : Desc<[boolean], object>
>a.bind : <T extends unknown[], U extends unknown[], R>(this: Desc<[...T, ...U], R>, ...args: T) => Desc<[...U], R>
>a : Desc<[string, number, boolean], object>
>bind : <T extends unknown[], U extends unknown[], R>(this: Desc<[...T, ...U], R>, ...args: T) => Desc<[...U], R>
>"" : ""
>1 : 1
// Repro from #39607
declare function getUser(id: string, options?: { x?: string }): string;
>getUser : (id: string, options?: { x?: string | undefined; } | undefined) => string
>id : string
>options : { x?: string | undefined; } | undefined
>x : string | undefined
declare function getOrgUser(id: string, orgId: number, options?: { y?: number, z?: boolean }): void;
>getOrgUser : (id: string, orgId: number, options?: { y?: number | undefined; z?: boolean | undefined; } | undefined) => void
>id : string
>orgId : number
>options : { y?: number | undefined; z?: boolean | undefined; } | undefined
>y : number | undefined
>z : boolean | undefined
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
>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, {}) : U
>method : (...args: [...T, object]) => U
>...args : T[number]
>args : [...T]
>{} : {}
}
callApi(getUser);
>callApi(getUser) : (id: string) => string
>callApi : <T extends unknown[] = [], U = void>(method: (...args: [...T, object]) => U) => (...args_0: T) => U
>getUser : (id: string, options?: { x?: string | undefined; } | undefined) => 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
>getOrgUser : (id: string, orgId: number, options?: { y?: number | undefined; z?: boolean | undefined; } | undefined) => void
// Repro from #40235
type Numbers = number[];
>Numbers : Numbers
type Unbounded = [...Numbers, boolean];
>Unbounded : [...number[], boolean]
const data: Unbounded = [false, false]; // Error
>data : [...number[], boolean]
>[false, false] : [false, false]
>false : false
>false : false
type U1 = [string, ...Numbers, boolean];
>U1 : [string, ...number[], boolean]
type U2 = [...[string, ...Numbers], boolean];
>U2 : [string, ...number[], boolean]
type U3 = [...[string, number], boolean];
>U3 : [string, number, boolean]