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}