• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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