• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// @strict: true
2// @declaration: true
3
4// infer to tuple element
5type X1<T extends any[]> =
6    T extends [infer U extends string] ? ["string", U] :
7    T extends [infer U extends number] ? ["number", U] :
8    never;
9
10type X1_T1 = X1<["a"]>; // ["string", "a"]
11type X1_T2 = X1<[1]>; // ["number", 1]
12type X1_T3 = X1<[object]>; // never
13
14// infer to argument
15type X2<T extends (...args: any[]) => void> =
16    T extends (a: infer U extends string) => void ? ["string", U] :
17    T extends (a: infer U extends number) => void ? ["number", U] :
18    never;
19
20type X2_T1 = X2<(a: "a") => void>; // ["string", "a"]
21type X2_T2 = X2<(a: 1) => void>; // ["number", 1]
22type X2_T3 = X2<(a: object) => void>; // never
23
24// infer to return type
25type X3<T extends (...args: any[]) => any> =
26    T extends (...args: any[]) => (infer U extends string) ? ["string", U] :
27    T extends (...args: any[]) => (infer U extends number) ? ["number", U] :
28    never;
29
30type X3_T1 = X3<() => "a">; // ["string", "a"]
31type X3_T2 = X3<() => 1>; // ["number", 1]
32type X3_T3 = X3<() => object>; // never
33
34// infer to instance type
35type X4<T extends new (...args: any[]) => any> =
36    T extends new (...args: any[]) => (infer U extends { a: string }) ? ["string", U] :
37    T extends new (...args: any[]) => (infer U extends { a: number }) ? ["number", U] :
38    never;
39
40type X4_T1 = X4<new () => { a: "a" }>; // ["string", { a: "a" }]
41type X4_T2 = X4<new () => { a: 1 }>; // ["number", { a: 1 }]
42type X4_T3 = X4<new () => { a: object }>; // never
43
44// infer to type argument
45type X5<T> =
46    T extends Promise<infer U extends string> ? ["string", U] :
47    T extends Promise<infer U extends number> ? ["number", U] :
48    never;
49
50type X5_T1 = X5<Promise<"a" | "b">>; // ["string", "a" | "b"]
51type X5_T2 = X5<Promise<1 | 2>>; // ["number", 1 | 2]
52type X5_T3 = X5<Promise<1n | 2n>>; // never
53
54// infer to property type
55type X6<T> =
56    T extends { a: infer U extends string } ? ["string", U] :
57    T extends { a: infer U extends number } ? ["number", U] :
58    never;
59
60type X6_T1 = X6<{ a: "a" }>; // ["string", "a"]
61type X6_T2 = X6<{ a: 1 }>; // ["number", 1]
62type X6_T3 = X6<{ a: object }>; // never
63
64// infer twice with same constraint
65type X7<T> =
66    T extends { a: infer U extends string, b: infer U extends string } ? ["string", U] :
67    T extends { a: infer U extends number, b: infer U extends number } ? ["number", U] :
68    never;
69
70type X7_T1 = X7<{ a: "a", b: "b" }>; // ["string", "a" | "b"]
71type X7_T2 = X7<{ a: 1, b: 2 }>; // ["number", 1 | 2]
72type X7_T3 = X7<{ a: object, b: object }>; // never
73type X7_T4 = X7<{ a: "a", b: 1 }>; // never
74
75// infer twice with missing second constraint (same behavior as class/interface)
76type X8<T> =
77    T extends { a: infer U extends string, b: infer U } ? ["string", U] :
78    T extends { a: infer U extends number, b: infer U } ? ["number", U] :
79    never;
80
81type X8_T1 = X8<{ a: "a", b: "b" }>; // ["string", "a" | "b"]
82type X8_T2 = X8<{ a: 1, b: 2 }>; // ["number", 1 | 2]
83type X8_T3 = X8<{ a: object, b: object }>; // never
84type X8_T4 = X8<{ a: "a", b: 1 }>; // never
85
86// infer twice with missing first constraint (same behavior as class/interface)
87type X9<T> =
88    T extends { a: infer U, b: infer U extends string } ? ["string", U] :
89    T extends { a: infer U, b: infer U extends number } ? ["number", U] :
90    never;
91
92type X9_T1 = X9<{ a: "a", b: "b" }>; // ["string", "a" | "b"]
93type X9_T2 = X9<{ a: 1, b: 2 }>; // ["number", 1 | 2]
94type X9_T3 = X9<{ a: object, b: object }>; // never
95type X9_T4 = X9<{ a: "a", b: 1 }>; // never
96
97// Speculative lookahead for `infer T extends U ?`
98type X10<T> = T extends (infer U extends number ? 1 : 0) ? 1 : 0; // ok, parsed as conditional
99type X10_Y1<T> = X10<T extends number ? 1 : 0>;
100type X10_T1_T1 = X10_Y1<number>;
101
102type X11<T> = T extends ((infer U) extends number ? 1 : 0) ? 1 : 0; // ok, parsed as conditional
103type X12<T> = T extends (infer U extends number) ? 1 : 0; // ok, parsed as `infer..extends` (no trailing `?`)
104type X13<T> = T extends infer U extends number ? 1 : 0; // ok, parsed as `infer..extends` (conditional types not allowed in 'extends type')
105type X14<T> = T extends keyof infer U extends number ? 1 : 0; // ok, parsed as `infer..extends` (precedence wouldn't have parsed the `?` as part of a type operator)
106type X15<T> = T extends { [P in infer U extends keyof T ? 1 : 0]: 1; } ? 1 : 0; // ok, parsed as conditional
107type X16<T> = T extends { [P in infer U extends keyof T]: 1; } ? 1 : 0; // ok, parsed as `infer..extends` (no trailing `?`)
108type X17<T> = T extends { [P in keyof T as infer U extends P ? 1 : 0]: 1; } ? 1 : 0; // ok, parsed as conditional
109type X18<T> = T extends { [P in keyof T as infer U extends P]: 1; } ? 1 : 0; // ok, parsed as `infer..extends` (no trailing `?`)
110
111type X19<T extends string | number> = T extends (infer U extends number) ? [T, U] : never;
112type X19_T1 = X19<"a">; // never
113type X19_T2 = X19<1>; // [1, 1]
114type X19_T3 = X19<1 | "a">; // [1, 1]
115
116type X20<T> = T extends (infer U extends number) ? T extends (infer V extends U) ? [T, U, V] : never : never;
117type X20_T1 = X20<1 | "a">; // [1, 1, 1]
118
119type X21<T, N extends number> = T extends (infer U extends N) ? [T, U] : never;
120type X21_T1 = X21<1, 1>; // [1, 1]
121type X21_T2 = X21<1 | "a", 1>; // [1, 1]
122type X21_T3 = X21<1 | 2, 1>; // [1, 1]
123type X21_T4 = X21<1 | 2, 2 | 3>; // [2, 2]
124type X21_T5 = X21<1 | 2, 3>; // never
125
126// from mongoose
127type IfEquals<X, Y, A, B> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? A : B;
128
129declare const x1: <T>() => (T extends infer U extends number ? 1 : 0);
130function f1() {
131    return x1;
132}
133
134type ExpectNumber<T extends number> = T;
135declare const x2: <T>() => (T extends ExpectNumber<infer U> ? 1 : 0);
136function f2() {
137    return x2;
138}