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