1// @strict: true 2 3type TestObj = { 4 a: string; 5 b: number; 6}; 7 8// Should be never but without an error 9type Result1 = TestObj[never]; 10 11type EmptyObj = {}; 12 13// Should be never but without an error 14type Result2 = EmptyObj[keyof EmptyObj]; 15 16declare function genericFn1<T>(obj: T): T[never]; 17 18// Should be never 19const result3 = genericFn1({ c: "ctest", d: "dtest" }); 20 21declare function genericFn2<T extends { [ind: string]: string }>( 22 obj: T 23): T[never]; 24 25// Should be never 26const result4 = genericFn2({ e: "etest", f: "ftest" }); 27 28declare function genericFn3< 29 T extends { [K in keyof T]: T[K] }, 30 U extends keyof T, 31 V extends keyof T 32>(obj: T, u: U, v: V): T[U & V]; 33 34// Should be never 35const result5 = genericFn3({ g: "gtest", h: "htest" }, "g", "h"); // 'g' & 'h' will reduce to never 36 37 38declare const obj: {a: string, b: number} 39declare const key: never 40 41const result6 = obj[key] 42 43// Expanded examples from https://github.com/Microsoft/TypeScript/issues/21988 44type RequiredPropNames<T> = { 45 [P in keyof T]-?: undefined extends T[P] ? never : P 46}[keyof T]; 47 48type OptionalPropNames<T> = { 49 [P in keyof T]-?: undefined extends T[P] ? P : never 50}[keyof T]; 51 52type RequiredProps<T> = { [P in RequiredPropNames<T>]: T[P] }; 53type OptionalProps<T> = { [P in OptionalPropNames<T>]?: T[P] }; 54 55type Match<Exp, Act> = [Exp] extends [Act] 56 ? ([Act] extends [Exp] ? "Match" : "Did not match 2") 57 : "Did not match 1"; 58 59type ExpectType<Exp, Act> = Match<Exp, Act> extends "Match" 60 ? ({} extends Exp ? Match<Required<Exp>, Required<Act>> : "Match") 61 : "Did not match"; 62 63type P3 = { a: string; b: number; c?: boolean }; 64type P2 = { a: string; c?: boolean }; 65type P1 = { c?: boolean }; 66type P0 = {}; 67 68type P3Names = RequiredPropNames<P3>; // expect 'a' | 'b' 69type P2Names = RequiredPropNames<P2>; // expect 'a' 70type P1Names = RequiredPropNames<P1>; // expect never 71type P0Names = RequiredPropNames<P0>; // expect never 72 73declare const p3NameTest: ExpectType<"a" | "b", P3Names>; 74declare const p2NameTest: ExpectType<"a", P2Names>; 75declare const p1NameTest: ExpectType<never, P1Names>; 76declare const p0NameTest: ExpectType<never, P0Names>; 77 78type P3Props = RequiredProps<P3>; // expect { a: string; b: number } 79type P2Props = RequiredProps<P2>; // expect { a: string; } 80type P1Props = RequiredProps<P1>; // expect {} 81type P0Props = RequiredProps<P0>; // expect {} 82 83declare const p3Test: ExpectType<{ a: string; b: number }, P3Props>; 84declare const p2Test: ExpectType<{ a: string }, P2Props>; 85declare const p1Test: ExpectType<{}, P1Props>; 86declare const p0Test: ExpectType<{}, P0Props>; 87 88type O3 = { a?: string; b?: number; c: boolean }; 89type O2 = { a?: string; c: boolean }; 90type O1 = { c: boolean }; 91type O0 = {}; 92 93type O3Names = OptionalPropNames<O3>; // expect 'a' | 'b' 94type O2Names = OptionalPropNames<O2>; // expect 'a' 95type O1Names = OptionalPropNames<O1>; // expect never 96type O0Names = OptionalPropNames<O0>; // expect never 97 98declare const o3NameTest: ExpectType<"a" | "b", O3Names>; 99declare const o2NameTest: ExpectType<"a", O2Names>; 100declare const o1NameTest: ExpectType<never, O1Names>; 101declare const o0NameTest: ExpectType<never, O0Names>; 102 103type O3Props = OptionalProps<O3>; // expect { a?: string | undefined; b?: number | undefined } 104type O2Props = OptionalProps<O2>; // expect { a?: string | undefined; } 105type O1Props = OptionalProps<O1>; // expect {} 106type O0Props = OptionalProps<O0>; // expect {} 107 108declare const o3Test: ExpectType<{ a?: string; b?: number }, O3Props>; 109declare const o2Test: ExpectType<{ a?: string }, O2Props>; 110declare const o1Test: ExpectType<{}, O1Props>; 111declare const o0Test: ExpectType<{}, O0Props>; 112 113// Repro from #23005 114 115type Example<T extends Record<'a', string>> = T['a']; 116 117type Res1 = Example<{ a: "x" } | { a: "y" }>; // "x" | "y" 118type Res2 = Example<{ a: "x" }>; // "x" 119type Res3 = Example<never>; // never 120