From 87a2d33a7a8e0358bfe0a045dbd347ce670910a2 Mon Sep 17 00:00:00 2001 From: Kevin Donnelly Date: Thu, 22 Mar 2018 08:48:45 -0500 Subject: [PATCH 1/4] Add tests showing existing behavior for indexing types with never. --- .../indexingTypesWithNever.errors.txt | 113 +++++ .../reference/indexingTypesWithNever.js | 114 +++++ .../reference/indexingTypesWithNever.symbols | 375 +++++++++++++++++ .../reference/indexingTypesWithNever.types | 389 ++++++++++++++++++ .../cases/compiler/indexingTypesWithNever.ts | 105 +++++ 5 files changed, 1096 insertions(+) create mode 100644 tests/baselines/reference/indexingTypesWithNever.errors.txt create mode 100644 tests/baselines/reference/indexingTypesWithNever.js create mode 100644 tests/baselines/reference/indexingTypesWithNever.symbols create mode 100644 tests/baselines/reference/indexingTypesWithNever.types create mode 100644 tests/cases/compiler/indexingTypesWithNever.ts diff --git a/tests/baselines/reference/indexingTypesWithNever.errors.txt b/tests/baselines/reference/indexingTypesWithNever.errors.txt new file mode 100644 index 0000000000000..e27af580c7af1 --- /dev/null +++ b/tests/baselines/reference/indexingTypesWithNever.errors.txt @@ -0,0 +1,113 @@ +tests/cases/compiler/indexingTypesWithNever.ts(7,24): error TS2538: Type 'never' cannot be used as an index type. +tests/cases/compiler/indexingTypesWithNever.ts(12,25): error TS2538: Type 'never' cannot be used as an index type. + + +==== tests/cases/compiler/indexingTypesWithNever.ts (2 errors) ==== + type TestObj = { + a: string; + b: number; + }; + + // Should be never but without an error + type Result1 = TestObj[never]; + ~~~~~ +!!! error TS2538: Type 'never' cannot be used as an index type. + + type EmptyObj = {}; + + // Should be never but without an error + type Result2 = EmptyObj[keyof EmptyObj]; + ~~~~~~~~~~~~~~ +!!! error TS2538: Type 'never' cannot be used as an index type. + + declare function genericFn1(obj: T): T[never]; + + // Should be never + const result3 = genericFn1({ c: "ctest", d: "dtest" }); + + declare function genericFn2( + obj: T + ): T[never]; + + // Should be never + const result4 = genericFn2({ e: "etest", f: "ftest" }); + + declare function genericFn3< + T extends { [K in keyof T]: T[K] }, + U extends keyof T, + V extends keyof T + >(obj: T, u: U, v: V): T[U & V]; + + // Should be never + const result5 = genericFn3({ g: "gtest", h: "htest" }, "g", "h"); // 'g' & 'h' will reduce to never + + // Expanded examples from https://github.com/Microsoft/TypeScript/issues/21988 + type RequiredPropNames = { + [P in keyof T]-?: undefined extends T[P] ? never : P + }[keyof T]; + + type OptionalPropNames = { + [P in keyof T]-?: undefined extends T[P] ? P : never + }[keyof T]; + + type RequiredProps = { [P in RequiredPropNames]: T[P] }; + type OptionalProps = { [P in OptionalPropNames]?: T[P] }; + + type Match = [Exp] extends [Act] + ? ([Act] extends [Exp] ? "Match" : "Did not match 2") + : "Did not match 1"; + + type ExpectType = Match extends "Match" + ? ({} extends Exp ? Match, Required> : "Match") + : "Did not match"; + + type P3 = { a: string; b: number; c?: boolean }; + type P2 = { a: string; c?: boolean }; + type P1 = { c?: boolean }; + type P0 = {}; + + type P3Names = RequiredPropNames; // expect 'a' | 'b' + type P2Names = RequiredPropNames; // expect 'a' + type P1Names = RequiredPropNames; // expect never + type P0Names = RequiredPropNames; // expect never + + declare const p3NameTest: ExpectType<"a" | "b", P3Names>; + declare const p2NameTest: ExpectType<"a", P2Names>; + declare const p1NameTest: ExpectType; + declare const p0NameTest: ExpectType; + + type P3Props = RequiredProps; // expect { a: string; b: number } + type P2Props = RequiredProps; // expect { a: string; } + type P1Props = RequiredProps; // expect {} + type P0Props = RequiredProps; // expect {} + + declare const p3Test: ExpectType<{ a: string; b: number }, P3Props>; + declare const p2Test: ExpectType<{ a: string }, P2Props>; + declare const p1Test: ExpectType<{}, P1Props>; + declare const p0Test: ExpectType<{}, P0Props>; + + type O3 = { a?: string; b?: number; c: boolean }; + type O2 = { a?: string; c: boolean }; + type O1 = { c: boolean }; + type O0 = {}; + + type O3Names = OptionalPropNames; // expect 'a' | 'b' + type O2Names = OptionalPropNames; // expect 'a' + type O1Names = OptionalPropNames; // expect never + type O0Names = OptionalPropNames; // expect never + + declare const o3NameTest: ExpectType<"a" | "b", O3Names>; + declare const o2NameTest: ExpectType<"a", O2Names>; + declare const o1NameTest: ExpectType; + declare const o0NameTest: ExpectType; + + type O3Props = OptionalProps; // expect { a?: string | undefined; b?: number | undefined } + type O2Props = OptionalProps; // expect { a?: string | undefined; } + type O1Props = OptionalProps; // expect {} + type O0Props = OptionalProps; // expect {} + + declare const o3Test: ExpectType<{ a?: string; b?: number }, O3Props>; + declare const o2Test: ExpectType<{ a?: string }, O2Props>; + declare const o1Test: ExpectType<{}, O1Props>; + declare const o0Test: ExpectType<{}, O0Props>; + \ No newline at end of file diff --git a/tests/baselines/reference/indexingTypesWithNever.js b/tests/baselines/reference/indexingTypesWithNever.js new file mode 100644 index 0000000000000..c5b414c1cf3d4 --- /dev/null +++ b/tests/baselines/reference/indexingTypesWithNever.js @@ -0,0 +1,114 @@ +//// [indexingTypesWithNever.ts] +type TestObj = { + a: string; + b: number; +}; + +// Should be never but without an error +type Result1 = TestObj[never]; + +type EmptyObj = {}; + +// Should be never but without an error +type Result2 = EmptyObj[keyof EmptyObj]; + +declare function genericFn1(obj: T): T[never]; + +// Should be never +const result3 = genericFn1({ c: "ctest", d: "dtest" }); + +declare function genericFn2( + obj: T +): T[never]; + +// Should be never +const result4 = genericFn2({ e: "etest", f: "ftest" }); + +declare function genericFn3< + T extends { [K in keyof T]: T[K] }, + U extends keyof T, + V extends keyof T +>(obj: T, u: U, v: V): T[U & V]; + +// Should be never +const result5 = genericFn3({ g: "gtest", h: "htest" }, "g", "h"); // 'g' & 'h' will reduce to never + +// Expanded examples from https://github.com/Microsoft/TypeScript/issues/21988 +type RequiredPropNames = { + [P in keyof T]-?: undefined extends T[P] ? never : P +}[keyof T]; + +type OptionalPropNames = { + [P in keyof T]-?: undefined extends T[P] ? P : never +}[keyof T]; + +type RequiredProps = { [P in RequiredPropNames]: T[P] }; +type OptionalProps = { [P in OptionalPropNames]?: T[P] }; + +type Match = [Exp] extends [Act] + ? ([Act] extends [Exp] ? "Match" : "Did not match 2") + : "Did not match 1"; + +type ExpectType = Match extends "Match" + ? ({} extends Exp ? Match, Required> : "Match") + : "Did not match"; + +type P3 = { a: string; b: number; c?: boolean }; +type P2 = { a: string; c?: boolean }; +type P1 = { c?: boolean }; +type P0 = {}; + +type P3Names = RequiredPropNames; // expect 'a' | 'b' +type P2Names = RequiredPropNames; // expect 'a' +type P1Names = RequiredPropNames; // expect never +type P0Names = RequiredPropNames; // expect never + +declare const p3NameTest: ExpectType<"a" | "b", P3Names>; +declare const p2NameTest: ExpectType<"a", P2Names>; +declare const p1NameTest: ExpectType; +declare const p0NameTest: ExpectType; + +type P3Props = RequiredProps; // expect { a: string; b: number } +type P2Props = RequiredProps; // expect { a: string; } +type P1Props = RequiredProps; // expect {} +type P0Props = RequiredProps; // expect {} + +declare const p3Test: ExpectType<{ a: string; b: number }, P3Props>; +declare const p2Test: ExpectType<{ a: string }, P2Props>; +declare const p1Test: ExpectType<{}, P1Props>; +declare const p0Test: ExpectType<{}, P0Props>; + +type O3 = { a?: string; b?: number; c: boolean }; +type O2 = { a?: string; c: boolean }; +type O1 = { c: boolean }; +type O0 = {}; + +type O3Names = OptionalPropNames; // expect 'a' | 'b' +type O2Names = OptionalPropNames; // expect 'a' +type O1Names = OptionalPropNames; // expect never +type O0Names = OptionalPropNames; // expect never + +declare const o3NameTest: ExpectType<"a" | "b", O3Names>; +declare const o2NameTest: ExpectType<"a", O2Names>; +declare const o1NameTest: ExpectType; +declare const o0NameTest: ExpectType; + +type O3Props = OptionalProps; // expect { a?: string | undefined; b?: number | undefined } +type O2Props = OptionalProps; // expect { a?: string | undefined; } +type O1Props = OptionalProps; // expect {} +type O0Props = OptionalProps; // expect {} + +declare const o3Test: ExpectType<{ a?: string; b?: number }, O3Props>; +declare const o2Test: ExpectType<{ a?: string }, O2Props>; +declare const o1Test: ExpectType<{}, O1Props>; +declare const o0Test: ExpectType<{}, O0Props>; + + +//// [indexingTypesWithNever.js] +"use strict"; +// Should be never +var result3 = genericFn1({ c: "ctest", d: "dtest" }); +// Should be never +var result4 = genericFn2({ e: "etest", f: "ftest" }); +// Should be never +var result5 = genericFn3({ g: "gtest", h: "htest" }, "g", "h"); // 'g' & 'h' will reduce to never diff --git a/tests/baselines/reference/indexingTypesWithNever.symbols b/tests/baselines/reference/indexingTypesWithNever.symbols new file mode 100644 index 0000000000000..0816fa19046fc --- /dev/null +++ b/tests/baselines/reference/indexingTypesWithNever.symbols @@ -0,0 +1,375 @@ +=== tests/cases/compiler/indexingTypesWithNever.ts === +type TestObj = { +>TestObj : Symbol(TestObj, Decl(indexingTypesWithNever.ts, 0, 0)) + + a: string; +>a : Symbol(a, Decl(indexingTypesWithNever.ts, 0, 16)) + + b: number; +>b : Symbol(b, Decl(indexingTypesWithNever.ts, 1, 12)) + +}; + +// Should be never but without an error +type Result1 = TestObj[never]; +>Result1 : Symbol(Result1, Decl(indexingTypesWithNever.ts, 3, 2)) +>TestObj : Symbol(TestObj, Decl(indexingTypesWithNever.ts, 0, 0)) + +type EmptyObj = {}; +>EmptyObj : Symbol(EmptyObj, Decl(indexingTypesWithNever.ts, 6, 30)) + +// Should be never but without an error +type Result2 = EmptyObj[keyof EmptyObj]; +>Result2 : Symbol(Result2, Decl(indexingTypesWithNever.ts, 8, 19)) +>EmptyObj : Symbol(EmptyObj, Decl(indexingTypesWithNever.ts, 6, 30)) +>EmptyObj : Symbol(EmptyObj, Decl(indexingTypesWithNever.ts, 6, 30)) + +declare function genericFn1(obj: T): T[never]; +>genericFn1 : Symbol(genericFn1, Decl(indexingTypesWithNever.ts, 11, 40)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 13, 28)) +>obj : Symbol(obj, Decl(indexingTypesWithNever.ts, 13, 31)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 13, 28)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 13, 28)) + +// Should be never +const result3 = genericFn1({ c: "ctest", d: "dtest" }); +>result3 : Symbol(result3, Decl(indexingTypesWithNever.ts, 16, 5)) +>genericFn1 : Symbol(genericFn1, Decl(indexingTypesWithNever.ts, 11, 40)) +>c : Symbol(c, Decl(indexingTypesWithNever.ts, 16, 28)) +>d : Symbol(d, Decl(indexingTypesWithNever.ts, 16, 40)) + +declare function genericFn2( +>genericFn2 : Symbol(genericFn2, Decl(indexingTypesWithNever.ts, 16, 55)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 18, 28)) +>ind : Symbol(ind, Decl(indexingTypesWithNever.ts, 18, 41)) + + obj: T +>obj : Symbol(obj, Decl(indexingTypesWithNever.ts, 18, 65)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 18, 28)) + +): T[never]; +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 18, 28)) + +// Should be never +const result4 = genericFn2({ e: "etest", f: "ftest" }); +>result4 : Symbol(result4, Decl(indexingTypesWithNever.ts, 23, 5)) +>genericFn2 : Symbol(genericFn2, Decl(indexingTypesWithNever.ts, 16, 55)) +>e : Symbol(e, Decl(indexingTypesWithNever.ts, 23, 28)) +>f : Symbol(f, Decl(indexingTypesWithNever.ts, 23, 40)) + +declare function genericFn3< +>genericFn3 : Symbol(genericFn3, Decl(indexingTypesWithNever.ts, 23, 55)) + + T extends { [K in keyof T]: T[K] }, +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 25, 28)) +>K : Symbol(K, Decl(indexingTypesWithNever.ts, 26, 15)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 25, 28)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 25, 28)) +>K : Symbol(K, Decl(indexingTypesWithNever.ts, 26, 15)) + + U extends keyof T, +>U : Symbol(U, Decl(indexingTypesWithNever.ts, 26, 37)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 25, 28)) + + V extends keyof T +>V : Symbol(V, Decl(indexingTypesWithNever.ts, 27, 20)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 25, 28)) + +>(obj: T, u: U, v: V): T[U & V]; +>obj : Symbol(obj, Decl(indexingTypesWithNever.ts, 29, 2)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 25, 28)) +>u : Symbol(u, Decl(indexingTypesWithNever.ts, 29, 9)) +>U : Symbol(U, Decl(indexingTypesWithNever.ts, 26, 37)) +>v : Symbol(v, Decl(indexingTypesWithNever.ts, 29, 15)) +>V : Symbol(V, Decl(indexingTypesWithNever.ts, 27, 20)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 25, 28)) +>U : Symbol(U, Decl(indexingTypesWithNever.ts, 26, 37)) +>V : Symbol(V, Decl(indexingTypesWithNever.ts, 27, 20)) + +// Should be never +const result5 = genericFn3({ g: "gtest", h: "htest" }, "g", "h"); // 'g' & 'h' will reduce to never +>result5 : Symbol(result5, Decl(indexingTypesWithNever.ts, 32, 5)) +>genericFn3 : Symbol(genericFn3, Decl(indexingTypesWithNever.ts, 23, 55)) +>g : Symbol(g, Decl(indexingTypesWithNever.ts, 32, 28)) +>h : Symbol(h, Decl(indexingTypesWithNever.ts, 32, 40)) + +// Expanded examples from https://github.com/Microsoft/TypeScript/issues/21988 +type RequiredPropNames = { +>RequiredPropNames : Symbol(RequiredPropNames, Decl(indexingTypesWithNever.ts, 32, 65)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 35, 23)) + + [P in keyof T]-?: undefined extends T[P] ? never : P +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 36, 3)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 35, 23)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 35, 23)) +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 36, 3)) +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 36, 3)) + +}[keyof T]; +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 35, 23)) + +type OptionalPropNames = { +>OptionalPropNames : Symbol(OptionalPropNames, Decl(indexingTypesWithNever.ts, 37, 11)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 39, 23)) + + [P in keyof T]-?: undefined extends T[P] ? P : never +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 40, 3)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 39, 23)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 39, 23)) +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 40, 3)) +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 40, 3)) + +}[keyof T]; +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 39, 23)) + +type RequiredProps = { [P in RequiredPropNames]: T[P] }; +>RequiredProps : Symbol(RequiredProps, Decl(indexingTypesWithNever.ts, 41, 11)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 43, 19)) +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 43, 27)) +>RequiredPropNames : Symbol(RequiredPropNames, Decl(indexingTypesWithNever.ts, 32, 65)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 43, 19)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 43, 19)) +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 43, 27)) + +type OptionalProps = { [P in OptionalPropNames]?: T[P] }; +>OptionalProps : Symbol(OptionalProps, Decl(indexingTypesWithNever.ts, 43, 62)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 44, 19)) +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 44, 27)) +>OptionalPropNames : Symbol(OptionalPropNames, Decl(indexingTypesWithNever.ts, 37, 11)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 44, 19)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 44, 19)) +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 44, 27)) + +type Match = [Exp] extends [Act] +>Match : Symbol(Match, Decl(indexingTypesWithNever.ts, 44, 63)) +>Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 46, 11)) +>Act : Symbol(Act, Decl(indexingTypesWithNever.ts, 46, 15)) +>Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 46, 11)) +>Act : Symbol(Act, Decl(indexingTypesWithNever.ts, 46, 15)) + + ? ([Act] extends [Exp] ? "Match" : "Did not match 2") +>Act : Symbol(Act, Decl(indexingTypesWithNever.ts, 46, 15)) +>Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 46, 11)) + + : "Did not match 1"; + +type ExpectType = Match extends "Match" +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) +>Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 50, 16)) +>Act : Symbol(Act, Decl(indexingTypesWithNever.ts, 50, 20)) +>Match : Symbol(Match, Decl(indexingTypesWithNever.ts, 44, 63)) +>Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 50, 16)) +>Act : Symbol(Act, Decl(indexingTypesWithNever.ts, 50, 20)) + + ? ({} extends Exp ? Match, Required> : "Match") +>Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 50, 16)) +>Match : Symbol(Match, Decl(indexingTypesWithNever.ts, 44, 63)) +>Required : Symbol(Required, Decl(lib.d.ts, --, --)) +>Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 50, 16)) +>Required : Symbol(Required, Decl(lib.d.ts, --, --)) +>Act : Symbol(Act, Decl(indexingTypesWithNever.ts, 50, 20)) + + : "Did not match"; + +type P3 = { a: string; b: number; c?: boolean }; +>P3 : Symbol(P3, Decl(indexingTypesWithNever.ts, 52, 20)) +>a : Symbol(a, Decl(indexingTypesWithNever.ts, 54, 11)) +>b : Symbol(b, Decl(indexingTypesWithNever.ts, 54, 22)) +>c : Symbol(c, Decl(indexingTypesWithNever.ts, 54, 33)) + +type P2 = { a: string; c?: boolean }; +>P2 : Symbol(P2, Decl(indexingTypesWithNever.ts, 54, 48)) +>a : Symbol(a, Decl(indexingTypesWithNever.ts, 55, 11)) +>c : Symbol(c, Decl(indexingTypesWithNever.ts, 55, 22)) + +type P1 = { c?: boolean }; +>P1 : Symbol(P1, Decl(indexingTypesWithNever.ts, 55, 37)) +>c : Symbol(c, Decl(indexingTypesWithNever.ts, 56, 11)) + +type P0 = {}; +>P0 : Symbol(P0, Decl(indexingTypesWithNever.ts, 56, 26)) + +type P3Names = RequiredPropNames; // expect 'a' | 'b' +>P3Names : Symbol(P3Names, Decl(indexingTypesWithNever.ts, 57, 13)) +>RequiredPropNames : Symbol(RequiredPropNames, Decl(indexingTypesWithNever.ts, 32, 65)) +>P3 : Symbol(P3, Decl(indexingTypesWithNever.ts, 52, 20)) + +type P2Names = RequiredPropNames; // expect 'a' +>P2Names : Symbol(P2Names, Decl(indexingTypesWithNever.ts, 59, 37)) +>RequiredPropNames : Symbol(RequiredPropNames, Decl(indexingTypesWithNever.ts, 32, 65)) +>P2 : Symbol(P2, Decl(indexingTypesWithNever.ts, 54, 48)) + +type P1Names = RequiredPropNames; // expect never +>P1Names : Symbol(P1Names, Decl(indexingTypesWithNever.ts, 60, 37)) +>RequiredPropNames : Symbol(RequiredPropNames, Decl(indexingTypesWithNever.ts, 32, 65)) +>P1 : Symbol(P1, Decl(indexingTypesWithNever.ts, 55, 37)) + +type P0Names = RequiredPropNames; // expect never +>P0Names : Symbol(P0Names, Decl(indexingTypesWithNever.ts, 61, 37)) +>RequiredPropNames : Symbol(RequiredPropNames, Decl(indexingTypesWithNever.ts, 32, 65)) +>P0 : Symbol(P0, Decl(indexingTypesWithNever.ts, 56, 26)) + +declare const p3NameTest: ExpectType<"a" | "b", P3Names>; +>p3NameTest : Symbol(p3NameTest, Decl(indexingTypesWithNever.ts, 64, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) +>P3Names : Symbol(P3Names, Decl(indexingTypesWithNever.ts, 57, 13)) + +declare const p2NameTest: ExpectType<"a", P2Names>; +>p2NameTest : Symbol(p2NameTest, Decl(indexingTypesWithNever.ts, 65, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) +>P2Names : Symbol(P2Names, Decl(indexingTypesWithNever.ts, 59, 37)) + +declare const p1NameTest: ExpectType; +>p1NameTest : Symbol(p1NameTest, Decl(indexingTypesWithNever.ts, 66, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) +>P1Names : Symbol(P1Names, Decl(indexingTypesWithNever.ts, 60, 37)) + +declare const p0NameTest: ExpectType; +>p0NameTest : Symbol(p0NameTest, Decl(indexingTypesWithNever.ts, 67, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) +>P0Names : Symbol(P0Names, Decl(indexingTypesWithNever.ts, 61, 37)) + +type P3Props = RequiredProps; // expect { a: string; b: number } +>P3Props : Symbol(P3Props, Decl(indexingTypesWithNever.ts, 67, 53)) +>RequiredProps : Symbol(RequiredProps, Decl(indexingTypesWithNever.ts, 41, 11)) +>P3 : Symbol(P3, Decl(indexingTypesWithNever.ts, 52, 20)) + +type P2Props = RequiredProps; // expect { a: string; } +>P2Props : Symbol(P2Props, Decl(indexingTypesWithNever.ts, 69, 33)) +>RequiredProps : Symbol(RequiredProps, Decl(indexingTypesWithNever.ts, 41, 11)) +>P2 : Symbol(P2, Decl(indexingTypesWithNever.ts, 54, 48)) + +type P1Props = RequiredProps; // expect {} +>P1Props : Symbol(P1Props, Decl(indexingTypesWithNever.ts, 70, 33)) +>RequiredProps : Symbol(RequiredProps, Decl(indexingTypesWithNever.ts, 41, 11)) +>P1 : Symbol(P1, Decl(indexingTypesWithNever.ts, 55, 37)) + +type P0Props = RequiredProps; // expect {} +>P0Props : Symbol(P0Props, Decl(indexingTypesWithNever.ts, 71, 33)) +>RequiredProps : Symbol(RequiredProps, Decl(indexingTypesWithNever.ts, 41, 11)) +>P0 : Symbol(P0, Decl(indexingTypesWithNever.ts, 56, 26)) + +declare const p3Test: ExpectType<{ a: string; b: number }, P3Props>; +>p3Test : Symbol(p3Test, Decl(indexingTypesWithNever.ts, 74, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) +>a : Symbol(a, Decl(indexingTypesWithNever.ts, 74, 34)) +>b : Symbol(b, Decl(indexingTypesWithNever.ts, 74, 45)) +>P3Props : Symbol(P3Props, Decl(indexingTypesWithNever.ts, 67, 53)) + +declare const p2Test: ExpectType<{ a: string }, P2Props>; +>p2Test : Symbol(p2Test, Decl(indexingTypesWithNever.ts, 75, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) +>a : Symbol(a, Decl(indexingTypesWithNever.ts, 75, 34)) +>P2Props : Symbol(P2Props, Decl(indexingTypesWithNever.ts, 69, 33)) + +declare const p1Test: ExpectType<{}, P1Props>; +>p1Test : Symbol(p1Test, Decl(indexingTypesWithNever.ts, 76, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) +>P1Props : Symbol(P1Props, Decl(indexingTypesWithNever.ts, 70, 33)) + +declare const p0Test: ExpectType<{}, P0Props>; +>p0Test : Symbol(p0Test, Decl(indexingTypesWithNever.ts, 77, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) +>P0Props : Symbol(P0Props, Decl(indexingTypesWithNever.ts, 71, 33)) + +type O3 = { a?: string; b?: number; c: boolean }; +>O3 : Symbol(O3, Decl(indexingTypesWithNever.ts, 77, 46)) +>a : Symbol(a, Decl(indexingTypesWithNever.ts, 79, 11)) +>b : Symbol(b, Decl(indexingTypesWithNever.ts, 79, 23)) +>c : Symbol(c, Decl(indexingTypesWithNever.ts, 79, 35)) + +type O2 = { a?: string; c: boolean }; +>O2 : Symbol(O2, Decl(indexingTypesWithNever.ts, 79, 49)) +>a : Symbol(a, Decl(indexingTypesWithNever.ts, 80, 11)) +>c : Symbol(c, Decl(indexingTypesWithNever.ts, 80, 23)) + +type O1 = { c: boolean }; +>O1 : Symbol(O1, Decl(indexingTypesWithNever.ts, 80, 37)) +>c : Symbol(c, Decl(indexingTypesWithNever.ts, 81, 11)) + +type O0 = {}; +>O0 : Symbol(O0, Decl(indexingTypesWithNever.ts, 81, 25)) + +type O3Names = OptionalPropNames; // expect 'a' | 'b' +>O3Names : Symbol(O3Names, Decl(indexingTypesWithNever.ts, 82, 13)) +>OptionalPropNames : Symbol(OptionalPropNames, Decl(indexingTypesWithNever.ts, 37, 11)) +>O3 : Symbol(O3, Decl(indexingTypesWithNever.ts, 77, 46)) + +type O2Names = OptionalPropNames; // expect 'a' +>O2Names : Symbol(O2Names, Decl(indexingTypesWithNever.ts, 84, 37)) +>OptionalPropNames : Symbol(OptionalPropNames, Decl(indexingTypesWithNever.ts, 37, 11)) +>O2 : Symbol(O2, Decl(indexingTypesWithNever.ts, 79, 49)) + +type O1Names = OptionalPropNames; // expect never +>O1Names : Symbol(O1Names, Decl(indexingTypesWithNever.ts, 85, 37)) +>OptionalPropNames : Symbol(OptionalPropNames, Decl(indexingTypesWithNever.ts, 37, 11)) +>O1 : Symbol(O1, Decl(indexingTypesWithNever.ts, 80, 37)) + +type O0Names = OptionalPropNames; // expect never +>O0Names : Symbol(O0Names, Decl(indexingTypesWithNever.ts, 86, 37)) +>OptionalPropNames : Symbol(OptionalPropNames, Decl(indexingTypesWithNever.ts, 37, 11)) +>O0 : Symbol(O0, Decl(indexingTypesWithNever.ts, 81, 25)) + +declare const o3NameTest: ExpectType<"a" | "b", O3Names>; +>o3NameTest : Symbol(o3NameTest, Decl(indexingTypesWithNever.ts, 89, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) +>O3Names : Symbol(O3Names, Decl(indexingTypesWithNever.ts, 82, 13)) + +declare const o2NameTest: ExpectType<"a", O2Names>; +>o2NameTest : Symbol(o2NameTest, Decl(indexingTypesWithNever.ts, 90, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) +>O2Names : Symbol(O2Names, Decl(indexingTypesWithNever.ts, 84, 37)) + +declare const o1NameTest: ExpectType; +>o1NameTest : Symbol(o1NameTest, Decl(indexingTypesWithNever.ts, 91, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) +>O1Names : Symbol(O1Names, Decl(indexingTypesWithNever.ts, 85, 37)) + +declare const o0NameTest: ExpectType; +>o0NameTest : Symbol(o0NameTest, Decl(indexingTypesWithNever.ts, 92, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) +>O0Names : Symbol(O0Names, Decl(indexingTypesWithNever.ts, 86, 37)) + +type O3Props = OptionalProps; // expect { a?: string | undefined; b?: number | undefined } +>O3Props : Symbol(O3Props, Decl(indexingTypesWithNever.ts, 92, 53)) +>OptionalProps : Symbol(OptionalProps, Decl(indexingTypesWithNever.ts, 43, 62)) +>O3 : Symbol(O3, Decl(indexingTypesWithNever.ts, 77, 46)) + +type O2Props = OptionalProps; // expect { a?: string | undefined; } +>O2Props : Symbol(O2Props, Decl(indexingTypesWithNever.ts, 94, 33)) +>OptionalProps : Symbol(OptionalProps, Decl(indexingTypesWithNever.ts, 43, 62)) +>O2 : Symbol(O2, Decl(indexingTypesWithNever.ts, 79, 49)) + +type O1Props = OptionalProps; // expect {} +>O1Props : Symbol(O1Props, Decl(indexingTypesWithNever.ts, 95, 33)) +>OptionalProps : Symbol(OptionalProps, Decl(indexingTypesWithNever.ts, 43, 62)) +>O1 : Symbol(O1, Decl(indexingTypesWithNever.ts, 80, 37)) + +type O0Props = OptionalProps; // expect {} +>O0Props : Symbol(O0Props, Decl(indexingTypesWithNever.ts, 96, 33)) +>OptionalProps : Symbol(OptionalProps, Decl(indexingTypesWithNever.ts, 43, 62)) +>O0 : Symbol(O0, Decl(indexingTypesWithNever.ts, 81, 25)) + +declare const o3Test: ExpectType<{ a?: string; b?: number }, O3Props>; +>o3Test : Symbol(o3Test, Decl(indexingTypesWithNever.ts, 99, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) +>a : Symbol(a, Decl(indexingTypesWithNever.ts, 99, 34)) +>b : Symbol(b, Decl(indexingTypesWithNever.ts, 99, 46)) +>O3Props : Symbol(O3Props, Decl(indexingTypesWithNever.ts, 92, 53)) + +declare const o2Test: ExpectType<{ a?: string }, O2Props>; +>o2Test : Symbol(o2Test, Decl(indexingTypesWithNever.ts, 100, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) +>a : Symbol(a, Decl(indexingTypesWithNever.ts, 100, 34)) +>O2Props : Symbol(O2Props, Decl(indexingTypesWithNever.ts, 94, 33)) + +declare const o1Test: ExpectType<{}, O1Props>; +>o1Test : Symbol(o1Test, Decl(indexingTypesWithNever.ts, 101, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) +>O1Props : Symbol(O1Props, Decl(indexingTypesWithNever.ts, 95, 33)) + +declare const o0Test: ExpectType<{}, O0Props>; +>o0Test : Symbol(o0Test, Decl(indexingTypesWithNever.ts, 102, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) +>O0Props : Symbol(O0Props, Decl(indexingTypesWithNever.ts, 96, 33)) + diff --git a/tests/baselines/reference/indexingTypesWithNever.types b/tests/baselines/reference/indexingTypesWithNever.types new file mode 100644 index 0000000000000..564e81af06dd5 --- /dev/null +++ b/tests/baselines/reference/indexingTypesWithNever.types @@ -0,0 +1,389 @@ +=== tests/cases/compiler/indexingTypesWithNever.ts === +type TestObj = { +>TestObj : TestObj + + a: string; +>a : string + + b: number; +>b : number + +}; + +// Should be never but without an error +type Result1 = TestObj[never]; +>Result1 : any +>TestObj : TestObj + +type EmptyObj = {}; +>EmptyObj : EmptyObj + +// Should be never but without an error +type Result2 = EmptyObj[keyof EmptyObj]; +>Result2 : any +>EmptyObj : EmptyObj +>EmptyObj : EmptyObj + +declare function genericFn1(obj: T): T[never]; +>genericFn1 : (obj: T) => T[never] +>T : T +>obj : T +>T : T +>T : T + +// Should be never +const result3 = genericFn1({ c: "ctest", d: "dtest" }); +>result3 : any +>genericFn1({ c: "ctest", d: "dtest" }) : any +>genericFn1 : (obj: T) => T[never] +>{ c: "ctest", d: "dtest" } : { c: string; d: string; } +>c : string +>"ctest" : "ctest" +>d : string +>"dtest" : "dtest" + +declare function genericFn2( +>genericFn2 : (obj: T) => T[never] +>T : T +>ind : string + + obj: T +>obj : T +>T : T + +): T[never]; +>T : T + +// Should be never +const result4 = genericFn2({ e: "etest", f: "ftest" }); +>result4 : any +>genericFn2({ e: "etest", f: "ftest" }) : any +>genericFn2 : (obj: T) => T[never] +>{ e: "etest", f: "ftest" } : { e: string; f: string; } +>e : string +>"etest" : "etest" +>f : string +>"ftest" : "ftest" + +declare function genericFn3< +>genericFn3 : (obj: T, u: U, v: V) => T[U & V] + + T extends { [K in keyof T]: T[K] }, +>T : T +>K : K +>T : T +>T : T +>K : K + + U extends keyof T, +>U : U +>T : T + + V extends keyof T +>V : V +>T : T + +>(obj: T, u: U, v: V): T[U & V]; +>obj : T +>T : T +>u : U +>U : U +>v : V +>V : V +>T : T +>U : U +>V : V + +// Should be never +const result5 = genericFn3({ g: "gtest", h: "htest" }, "g", "h"); // 'g' & 'h' will reduce to never +>result5 : any +>genericFn3({ g: "gtest", h: "htest" }, "g", "h") : any +>genericFn3 : (obj: T, u: U, v: V) => T[U & V] +>{ g: "gtest", h: "htest" } : { g: string; h: string; } +>g : string +>"gtest" : "gtest" +>h : string +>"htest" : "htest" +>"g" : "g" +>"h" : "h" + +// Expanded examples from https://github.com/Microsoft/TypeScript/issues/21988 +type RequiredPropNames = { +>RequiredPropNames : { [P in keyof T]-?: undefined extends T[P] ? never : P; }[keyof T] +>T : T + + [P in keyof T]-?: undefined extends T[P] ? never : P +>P : P +>T : T +>T : T +>P : P +>P : P + +}[keyof T]; +>T : T + +type OptionalPropNames = { +>OptionalPropNames : { [P in keyof T]-?: undefined extends T[P] ? P : never; }[keyof T] +>T : T + + [P in keyof T]-?: undefined extends T[P] ? P : never +>P : P +>T : T +>T : T +>P : P +>P : P + +}[keyof T]; +>T : T + +type RequiredProps = { [P in RequiredPropNames]: T[P] }; +>RequiredProps : RequiredProps +>T : T +>P : P +>RequiredPropNames : { [P in keyof T]-?: undefined extends T[P] ? never : P; }[keyof T] +>T : T +>T : T +>P : P + +type OptionalProps = { [P in OptionalPropNames]?: T[P] }; +>OptionalProps : OptionalProps +>T : T +>P : P +>OptionalPropNames : { [P in keyof T]-?: undefined extends T[P] ? P : never; }[keyof T] +>T : T +>T : T +>P : P + +type Match = [Exp] extends [Act] +>Match : Match +>Exp : Exp +>Act : Act +>Exp : Exp +>Act : Act + + ? ([Act] extends [Exp] ? "Match" : "Did not match 2") +>Act : Act +>Exp : Exp + + : "Did not match 1"; + +type ExpectType = Match extends "Match" +>ExpectType : ExpectType +>Exp : Exp +>Act : Act +>Match : Match +>Exp : Exp +>Act : Act + + ? ({} extends Exp ? Match, Required> : "Match") +>Exp : Exp +>Match : Match +>Required : Required +>Exp : Exp +>Required : Required +>Act : Act + + : "Did not match"; + +type P3 = { a: string; b: number; c?: boolean }; +>P3 : P3 +>a : string +>b : number +>c : boolean | undefined + +type P2 = { a: string; c?: boolean }; +>P2 : P2 +>a : string +>c : boolean | undefined + +type P1 = { c?: boolean }; +>P1 : P1 +>c : boolean | undefined + +type P0 = {}; +>P0 : P0 + +type P3Names = RequiredPropNames; // expect 'a' | 'b' +>P3Names : "a" | "b" +>RequiredPropNames : { [P in keyof T]-?: undefined extends T[P] ? never : P; }[keyof T] +>P3 : P3 + +type P2Names = RequiredPropNames; // expect 'a' +>P2Names : "a" +>RequiredPropNames : { [P in keyof T]-?: undefined extends T[P] ? never : P; }[keyof T] +>P2 : P2 + +type P1Names = RequiredPropNames; // expect never +>P1Names : never +>RequiredPropNames : { [P in keyof T]-?: undefined extends T[P] ? never : P; }[keyof T] +>P1 : P1 + +type P0Names = RequiredPropNames; // expect never +>P0Names : any +>RequiredPropNames : { [P in keyof T]-?: undefined extends T[P] ? never : P; }[keyof T] +>P0 : P0 + +declare const p3NameTest: ExpectType<"a" | "b", P3Names>; +>p3NameTest : "Match" +>ExpectType : ExpectType +>P3Names : "a" | "b" + +declare const p2NameTest: ExpectType<"a", P2Names>; +>p2NameTest : "Match" +>ExpectType : ExpectType +>P2Names : "a" + +declare const p1NameTest: ExpectType; +>p1NameTest : "Match" +>ExpectType : ExpectType +>P1Names : never + +declare const p0NameTest: ExpectType; +>p0NameTest : "Did not match" +>ExpectType : ExpectType +>P0Names : any + +type P3Props = RequiredProps; // expect { a: string; b: number } +>P3Props : RequiredProps +>RequiredProps : RequiredProps +>P3 : P3 + +type P2Props = RequiredProps; // expect { a: string; } +>P2Props : RequiredProps +>RequiredProps : RequiredProps +>P2 : P2 + +type P1Props = RequiredProps; // expect {} +>P1Props : RequiredProps +>RequiredProps : RequiredProps +>P1 : P1 + +type P0Props = RequiredProps; // expect {} +>P0Props : RequiredProps +>RequiredProps : RequiredProps +>P0 : P0 + +declare const p3Test: ExpectType<{ a: string; b: number }, P3Props>; +>p3Test : "Match" +>ExpectType : ExpectType +>a : string +>b : number +>P3Props : RequiredProps + +declare const p2Test: ExpectType<{ a: string }, P2Props>; +>p2Test : "Match" +>ExpectType : ExpectType +>a : string +>P2Props : RequiredProps + +declare const p1Test: ExpectType<{}, P1Props>; +>p1Test : "Match" +>ExpectType : ExpectType +>P1Props : RequiredProps + +declare const p0Test: ExpectType<{}, P0Props>; +>p0Test : "Match" +>ExpectType : ExpectType +>P0Props : RequiredProps + +type O3 = { a?: string; b?: number; c: boolean }; +>O3 : O3 +>a : string | undefined +>b : number | undefined +>c : boolean + +type O2 = { a?: string; c: boolean }; +>O2 : O2 +>a : string | undefined +>c : boolean + +type O1 = { c: boolean }; +>O1 : O1 +>c : boolean + +type O0 = {}; +>O0 : O0 + +type O3Names = OptionalPropNames; // expect 'a' | 'b' +>O3Names : "a" | "b" +>OptionalPropNames : { [P in keyof T]-?: undefined extends T[P] ? P : never; }[keyof T] +>O3 : O3 + +type O2Names = OptionalPropNames; // expect 'a' +>O2Names : "a" +>OptionalPropNames : { [P in keyof T]-?: undefined extends T[P] ? P : never; }[keyof T] +>O2 : O2 + +type O1Names = OptionalPropNames; // expect never +>O1Names : never +>OptionalPropNames : { [P in keyof T]-?: undefined extends T[P] ? P : never; }[keyof T] +>O1 : O1 + +type O0Names = OptionalPropNames; // expect never +>O0Names : any +>OptionalPropNames : { [P in keyof T]-?: undefined extends T[P] ? P : never; }[keyof T] +>O0 : O0 + +declare const o3NameTest: ExpectType<"a" | "b", O3Names>; +>o3NameTest : "Match" +>ExpectType : ExpectType +>O3Names : "a" | "b" + +declare const o2NameTest: ExpectType<"a", O2Names>; +>o2NameTest : "Match" +>ExpectType : ExpectType +>O2Names : "a" + +declare const o1NameTest: ExpectType; +>o1NameTest : "Match" +>ExpectType : ExpectType +>O1Names : never + +declare const o0NameTest: ExpectType; +>o0NameTest : "Did not match" +>ExpectType : ExpectType +>O0Names : any + +type O3Props = OptionalProps; // expect { a?: string | undefined; b?: number | undefined } +>O3Props : OptionalProps +>OptionalProps : OptionalProps +>O3 : O3 + +type O2Props = OptionalProps; // expect { a?: string | undefined; } +>O2Props : OptionalProps +>OptionalProps : OptionalProps +>O2 : O2 + +type O1Props = OptionalProps; // expect {} +>O1Props : OptionalProps +>OptionalProps : OptionalProps +>O1 : O1 + +type O0Props = OptionalProps; // expect {} +>O0Props : OptionalProps +>OptionalProps : OptionalProps +>O0 : O0 + +declare const o3Test: ExpectType<{ a?: string; b?: number }, O3Props>; +>o3Test : "Match" +>ExpectType : ExpectType +>a : string | undefined +>b : number | undefined +>O3Props : OptionalProps + +declare const o2Test: ExpectType<{ a?: string }, O2Props>; +>o2Test : "Match" +>ExpectType : ExpectType +>a : string | undefined +>O2Props : OptionalProps + +declare const o1Test: ExpectType<{}, O1Props>; +>o1Test : "Match" +>ExpectType : ExpectType +>O1Props : OptionalProps + +declare const o0Test: ExpectType<{}, O0Props>; +>o0Test : "Match" +>ExpectType : ExpectType +>O0Props : OptionalProps + diff --git a/tests/cases/compiler/indexingTypesWithNever.ts b/tests/cases/compiler/indexingTypesWithNever.ts new file mode 100644 index 0000000000000..467b74eafc67f --- /dev/null +++ b/tests/cases/compiler/indexingTypesWithNever.ts @@ -0,0 +1,105 @@ +// @strict: true + +type TestObj = { + a: string; + b: number; +}; + +// Should be never but without an error +type Result1 = TestObj[never]; + +type EmptyObj = {}; + +// Should be never but without an error +type Result2 = EmptyObj[keyof EmptyObj]; + +declare function genericFn1(obj: T): T[never]; + +// Should be never +const result3 = genericFn1({ c: "ctest", d: "dtest" }); + +declare function genericFn2( + obj: T +): T[never]; + +// Should be never +const result4 = genericFn2({ e: "etest", f: "ftest" }); + +declare function genericFn3< + T extends { [K in keyof T]: T[K] }, + U extends keyof T, + V extends keyof T +>(obj: T, u: U, v: V): T[U & V]; + +// Should be never +const result5 = genericFn3({ g: "gtest", h: "htest" }, "g", "h"); // 'g' & 'h' will reduce to never + +// Expanded examples from https://github.com/Microsoft/TypeScript/issues/21988 +type RequiredPropNames = { + [P in keyof T]-?: undefined extends T[P] ? never : P +}[keyof T]; + +type OptionalPropNames = { + [P in keyof T]-?: undefined extends T[P] ? P : never +}[keyof T]; + +type RequiredProps = { [P in RequiredPropNames]: T[P] }; +type OptionalProps = { [P in OptionalPropNames]?: T[P] }; + +type Match = [Exp] extends [Act] + ? ([Act] extends [Exp] ? "Match" : "Did not match 2") + : "Did not match 1"; + +type ExpectType = Match extends "Match" + ? ({} extends Exp ? Match, Required> : "Match") + : "Did not match"; + +type P3 = { a: string; b: number; c?: boolean }; +type P2 = { a: string; c?: boolean }; +type P1 = { c?: boolean }; +type P0 = {}; + +type P3Names = RequiredPropNames; // expect 'a' | 'b' +type P2Names = RequiredPropNames; // expect 'a' +type P1Names = RequiredPropNames; // expect never +type P0Names = RequiredPropNames; // expect never + +declare const p3NameTest: ExpectType<"a" | "b", P3Names>; +declare const p2NameTest: ExpectType<"a", P2Names>; +declare const p1NameTest: ExpectType; +declare const p0NameTest: ExpectType; + +type P3Props = RequiredProps; // expect { a: string; b: number } +type P2Props = RequiredProps; // expect { a: string; } +type P1Props = RequiredProps; // expect {} +type P0Props = RequiredProps; // expect {} + +declare const p3Test: ExpectType<{ a: string; b: number }, P3Props>; +declare const p2Test: ExpectType<{ a: string }, P2Props>; +declare const p1Test: ExpectType<{}, P1Props>; +declare const p0Test: ExpectType<{}, P0Props>; + +type O3 = { a?: string; b?: number; c: boolean }; +type O2 = { a?: string; c: boolean }; +type O1 = { c: boolean }; +type O0 = {}; + +type O3Names = OptionalPropNames; // expect 'a' | 'b' +type O2Names = OptionalPropNames; // expect 'a' +type O1Names = OptionalPropNames; // expect never +type O0Names = OptionalPropNames; // expect never + +declare const o3NameTest: ExpectType<"a" | "b", O3Names>; +declare const o2NameTest: ExpectType<"a", O2Names>; +declare const o1NameTest: ExpectType; +declare const o0NameTest: ExpectType; + +type O3Props = OptionalProps; // expect { a?: string | undefined; b?: number | undefined } +type O2Props = OptionalProps; // expect { a?: string | undefined; } +type O1Props = OptionalProps; // expect {} +type O0Props = OptionalProps; // expect {} + +declare const o3Test: ExpectType<{ a?: string; b?: number }, O3Props>; +declare const o2Test: ExpectType<{ a?: string }, O2Props>; +declare const o1Test: ExpectType<{}, O1Props>; +declare const o0Test: ExpectType<{}, O0Props>; From f0ca9ec24be3c9c21857834cca85269d2731bb3d Mon Sep 17 00:00:00 2001 From: Kevin Donnelly Date: Thu, 22 Mar 2018 08:53:37 -0500 Subject: [PATCH 2/4] Make T[never] = never instead of erroring or being any. And update the baselines for the tests for this change. --- src/compiler/checker.ts | 3 + .../indexingTypesWithNever.errors.txt | 113 ------------------ .../reference/indexingTypesWithNever.types | 24 ++-- 3 files changed, 15 insertions(+), 125 deletions(-) delete mode 100644 tests/baselines/reference/indexingTypesWithNever.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5bf1f022869ee..d4c5a5695dd2c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8163,6 +8163,9 @@ namespace ts { return anyType; } } + if (indexType.flags & TypeFlags.Never) { + return neverType; + } if (accessNode) { const indexNode = accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode.argumentExpression : accessNode.indexType; if (indexType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) { diff --git a/tests/baselines/reference/indexingTypesWithNever.errors.txt b/tests/baselines/reference/indexingTypesWithNever.errors.txt deleted file mode 100644 index e27af580c7af1..0000000000000 --- a/tests/baselines/reference/indexingTypesWithNever.errors.txt +++ /dev/null @@ -1,113 +0,0 @@ -tests/cases/compiler/indexingTypesWithNever.ts(7,24): error TS2538: Type 'never' cannot be used as an index type. -tests/cases/compiler/indexingTypesWithNever.ts(12,25): error TS2538: Type 'never' cannot be used as an index type. - - -==== tests/cases/compiler/indexingTypesWithNever.ts (2 errors) ==== - type TestObj = { - a: string; - b: number; - }; - - // Should be never but without an error - type Result1 = TestObj[never]; - ~~~~~ -!!! error TS2538: Type 'never' cannot be used as an index type. - - type EmptyObj = {}; - - // Should be never but without an error - type Result2 = EmptyObj[keyof EmptyObj]; - ~~~~~~~~~~~~~~ -!!! error TS2538: Type 'never' cannot be used as an index type. - - declare function genericFn1(obj: T): T[never]; - - // Should be never - const result3 = genericFn1({ c: "ctest", d: "dtest" }); - - declare function genericFn2( - obj: T - ): T[never]; - - // Should be never - const result4 = genericFn2({ e: "etest", f: "ftest" }); - - declare function genericFn3< - T extends { [K in keyof T]: T[K] }, - U extends keyof T, - V extends keyof T - >(obj: T, u: U, v: V): T[U & V]; - - // Should be never - const result5 = genericFn3({ g: "gtest", h: "htest" }, "g", "h"); // 'g' & 'h' will reduce to never - - // Expanded examples from https://github.com/Microsoft/TypeScript/issues/21988 - type RequiredPropNames = { - [P in keyof T]-?: undefined extends T[P] ? never : P - }[keyof T]; - - type OptionalPropNames = { - [P in keyof T]-?: undefined extends T[P] ? P : never - }[keyof T]; - - type RequiredProps = { [P in RequiredPropNames]: T[P] }; - type OptionalProps = { [P in OptionalPropNames]?: T[P] }; - - type Match = [Exp] extends [Act] - ? ([Act] extends [Exp] ? "Match" : "Did not match 2") - : "Did not match 1"; - - type ExpectType = Match extends "Match" - ? ({} extends Exp ? Match, Required> : "Match") - : "Did not match"; - - type P3 = { a: string; b: number; c?: boolean }; - type P2 = { a: string; c?: boolean }; - type P1 = { c?: boolean }; - type P0 = {}; - - type P3Names = RequiredPropNames; // expect 'a' | 'b' - type P2Names = RequiredPropNames; // expect 'a' - type P1Names = RequiredPropNames; // expect never - type P0Names = RequiredPropNames; // expect never - - declare const p3NameTest: ExpectType<"a" | "b", P3Names>; - declare const p2NameTest: ExpectType<"a", P2Names>; - declare const p1NameTest: ExpectType; - declare const p0NameTest: ExpectType; - - type P3Props = RequiredProps; // expect { a: string; b: number } - type P2Props = RequiredProps; // expect { a: string; } - type P1Props = RequiredProps; // expect {} - type P0Props = RequiredProps; // expect {} - - declare const p3Test: ExpectType<{ a: string; b: number }, P3Props>; - declare const p2Test: ExpectType<{ a: string }, P2Props>; - declare const p1Test: ExpectType<{}, P1Props>; - declare const p0Test: ExpectType<{}, P0Props>; - - type O3 = { a?: string; b?: number; c: boolean }; - type O2 = { a?: string; c: boolean }; - type O1 = { c: boolean }; - type O0 = {}; - - type O3Names = OptionalPropNames; // expect 'a' | 'b' - type O2Names = OptionalPropNames; // expect 'a' - type O1Names = OptionalPropNames; // expect never - type O0Names = OptionalPropNames; // expect never - - declare const o3NameTest: ExpectType<"a" | "b", O3Names>; - declare const o2NameTest: ExpectType<"a", O2Names>; - declare const o1NameTest: ExpectType; - declare const o0NameTest: ExpectType; - - type O3Props = OptionalProps; // expect { a?: string | undefined; b?: number | undefined } - type O2Props = OptionalProps; // expect { a?: string | undefined; } - type O1Props = OptionalProps; // expect {} - type O0Props = OptionalProps; // expect {} - - declare const o3Test: ExpectType<{ a?: string; b?: number }, O3Props>; - declare const o2Test: ExpectType<{ a?: string }, O2Props>; - declare const o1Test: ExpectType<{}, O1Props>; - declare const o0Test: ExpectType<{}, O0Props>; - \ No newline at end of file diff --git a/tests/baselines/reference/indexingTypesWithNever.types b/tests/baselines/reference/indexingTypesWithNever.types index 564e81af06dd5..733fd875d4fe9 100644 --- a/tests/baselines/reference/indexingTypesWithNever.types +++ b/tests/baselines/reference/indexingTypesWithNever.types @@ -12,7 +12,7 @@ type TestObj = { // Should be never but without an error type Result1 = TestObj[never]; ->Result1 : any +>Result1 : never >TestObj : TestObj type EmptyObj = {}; @@ -20,7 +20,7 @@ type EmptyObj = {}; // Should be never but without an error type Result2 = EmptyObj[keyof EmptyObj]; ->Result2 : any +>Result2 : never >EmptyObj : EmptyObj >EmptyObj : EmptyObj @@ -33,8 +33,8 @@ declare function genericFn1(obj: T): T[never]; // Should be never const result3 = genericFn1({ c: "ctest", d: "dtest" }); ->result3 : any ->genericFn1({ c: "ctest", d: "dtest" }) : any +>result3 : never +>genericFn1({ c: "ctest", d: "dtest" }) : never >genericFn1 : (obj: T) => T[never] >{ c: "ctest", d: "dtest" } : { c: string; d: string; } >c : string @@ -56,8 +56,8 @@ declare function genericFn2( // Should be never const result4 = genericFn2({ e: "etest", f: "ftest" }); ->result4 : any ->genericFn2({ e: "etest", f: "ftest" }) : any +>result4 : never +>genericFn2({ e: "etest", f: "ftest" }) : never >genericFn2 : (obj: T) => T[never] >{ e: "etest", f: "ftest" } : { e: string; f: string; } >e : string @@ -219,7 +219,7 @@ type P1Names = RequiredPropNames; // expect never >P1 : P1 type P0Names = RequiredPropNames; // expect never ->P0Names : any +>P0Names : never >RequiredPropNames : { [P in keyof T]-?: undefined extends T[P] ? never : P; }[keyof T] >P0 : P0 @@ -239,9 +239,9 @@ declare const p1NameTest: ExpectType; >P1Names : never declare const p0NameTest: ExpectType; ->p0NameTest : "Did not match" +>p0NameTest : "Match" >ExpectType : ExpectType ->P0Names : any +>P0Names : never type P3Props = RequiredProps; // expect { a: string; b: number } >P3Props : RequiredProps @@ -320,7 +320,7 @@ type O1Names = OptionalPropNames; // expect never >O1 : O1 type O0Names = OptionalPropNames; // expect never ->O0Names : any +>O0Names : never >OptionalPropNames : { [P in keyof T]-?: undefined extends T[P] ? P : never; }[keyof T] >O0 : O0 @@ -340,9 +340,9 @@ declare const o1NameTest: ExpectType; >O1Names : never declare const o0NameTest: ExpectType; ->o0NameTest : "Did not match" +>o0NameTest : "Match" >ExpectType : ExpectType ->O0Names : any +>O0Names : never type O3Props = OptionalProps; // expect { a?: string | undefined; b?: number | undefined } >O3Props : OptionalProps From 7f95ca5ae7209169cab3ecb0897bad5ddc132f10 Mon Sep 17 00:00:00 2001 From: Kevin Donnelly Date: Mon, 26 Mar 2018 19:09:46 -0500 Subject: [PATCH 3/4] Add test case for indexing an expression with never showing existing behavior. --- .../indexingTypesWithNever.errors.txt | 116 ++++++ .../reference/indexingTypesWithNever.js | 7 + .../reference/indexingTypesWithNever.symbols | 352 +++++++++--------- .../reference/indexingTypesWithNever.types | 15 + .../cases/compiler/indexingTypesWithNever.ts | 6 + 5 files changed, 327 insertions(+), 169 deletions(-) create mode 100644 tests/baselines/reference/indexingTypesWithNever.errors.txt diff --git a/tests/baselines/reference/indexingTypesWithNever.errors.txt b/tests/baselines/reference/indexingTypesWithNever.errors.txt new file mode 100644 index 0000000000000..713a24e816f72 --- /dev/null +++ b/tests/baselines/reference/indexingTypesWithNever.errors.txt @@ -0,0 +1,116 @@ +tests/cases/compiler/indexingTypesWithNever.ts(39,17): error TS7017: Element implicitly has an 'any' type because type '{ a: string; b: number; }' has no index signature. + + +==== tests/cases/compiler/indexingTypesWithNever.ts (1 errors) ==== + type TestObj = { + a: string; + b: number; + }; + + // Should be never but without an error + type Result1 = TestObj[never]; + + type EmptyObj = {}; + + // Should be never but without an error + type Result2 = EmptyObj[keyof EmptyObj]; + + declare function genericFn1(obj: T): T[never]; + + // Should be never + const result3 = genericFn1({ c: "ctest", d: "dtest" }); + + declare function genericFn2( + obj: T + ): T[never]; + + // Should be never + const result4 = genericFn2({ e: "etest", f: "ftest" }); + + declare function genericFn3< + T extends { [K in keyof T]: T[K] }, + U extends keyof T, + V extends keyof T + >(obj: T, u: U, v: V): T[U & V]; + + // Should be never + const result5 = genericFn3({ g: "gtest", h: "htest" }, "g", "h"); // 'g' & 'h' will reduce to never + + + declare const obj: {a: string, b: number} + declare const key: never + + const result6 = obj[key] + ~~~~~~~~ +!!! error TS7017: Element implicitly has an 'any' type because type '{ a: string; b: number; }' has no index signature. + + // Expanded examples from https://github.com/Microsoft/TypeScript/issues/21988 + type RequiredPropNames = { + [P in keyof T]-?: undefined extends T[P] ? never : P + }[keyof T]; + + type OptionalPropNames = { + [P in keyof T]-?: undefined extends T[P] ? P : never + }[keyof T]; + + type RequiredProps = { [P in RequiredPropNames]: T[P] }; + type OptionalProps = { [P in OptionalPropNames]?: T[P] }; + + type Match = [Exp] extends [Act] + ? ([Act] extends [Exp] ? "Match" : "Did not match 2") + : "Did not match 1"; + + type ExpectType = Match extends "Match" + ? ({} extends Exp ? Match, Required> : "Match") + : "Did not match"; + + type P3 = { a: string; b: number; c?: boolean }; + type P2 = { a: string; c?: boolean }; + type P1 = { c?: boolean }; + type P0 = {}; + + type P3Names = RequiredPropNames; // expect 'a' | 'b' + type P2Names = RequiredPropNames; // expect 'a' + type P1Names = RequiredPropNames; // expect never + type P0Names = RequiredPropNames; // expect never + + declare const p3NameTest: ExpectType<"a" | "b", P3Names>; + declare const p2NameTest: ExpectType<"a", P2Names>; + declare const p1NameTest: ExpectType; + declare const p0NameTest: ExpectType; + + type P3Props = RequiredProps; // expect { a: string; b: number } + type P2Props = RequiredProps; // expect { a: string; } + type P1Props = RequiredProps; // expect {} + type P0Props = RequiredProps; // expect {} + + declare const p3Test: ExpectType<{ a: string; b: number }, P3Props>; + declare const p2Test: ExpectType<{ a: string }, P2Props>; + declare const p1Test: ExpectType<{}, P1Props>; + declare const p0Test: ExpectType<{}, P0Props>; + + type O3 = { a?: string; b?: number; c: boolean }; + type O2 = { a?: string; c: boolean }; + type O1 = { c: boolean }; + type O0 = {}; + + type O3Names = OptionalPropNames; // expect 'a' | 'b' + type O2Names = OptionalPropNames; // expect 'a' + type O1Names = OptionalPropNames; // expect never + type O0Names = OptionalPropNames; // expect never + + declare const o3NameTest: ExpectType<"a" | "b", O3Names>; + declare const o2NameTest: ExpectType<"a", O2Names>; + declare const o1NameTest: ExpectType; + declare const o0NameTest: ExpectType; + + type O3Props = OptionalProps; // expect { a?: string | undefined; b?: number | undefined } + type O2Props = OptionalProps; // expect { a?: string | undefined; } + type O1Props = OptionalProps; // expect {} + type O0Props = OptionalProps; // expect {} + + declare const o3Test: ExpectType<{ a?: string; b?: number }, O3Props>; + declare const o2Test: ExpectType<{ a?: string }, O2Props>; + declare const o1Test: ExpectType<{}, O1Props>; + declare const o0Test: ExpectType<{}, O0Props>; + \ No newline at end of file diff --git a/tests/baselines/reference/indexingTypesWithNever.js b/tests/baselines/reference/indexingTypesWithNever.js index c5b414c1cf3d4..4e174fc4c9d91 100644 --- a/tests/baselines/reference/indexingTypesWithNever.js +++ b/tests/baselines/reference/indexingTypesWithNever.js @@ -33,6 +33,12 @@ declare function genericFn3< // Should be never const result5 = genericFn3({ g: "gtest", h: "htest" }, "g", "h"); // 'g' & 'h' will reduce to never + +declare const obj: {a: string, b: number} +declare const key: never + +const result6 = obj[key] + // Expanded examples from https://github.com/Microsoft/TypeScript/issues/21988 type RequiredPropNames = { [P in keyof T]-?: undefined extends T[P] ? never : P @@ -112,3 +118,4 @@ var result3 = genericFn1({ c: "ctest", d: "dtest" }); var result4 = genericFn2({ e: "etest", f: "ftest" }); // Should be never var result5 = genericFn3({ g: "gtest", h: "htest" }, "g", "h"); // 'g' & 'h' will reduce to never +var result6 = obj[key]; diff --git a/tests/baselines/reference/indexingTypesWithNever.symbols b/tests/baselines/reference/indexingTypesWithNever.symbols index 0816fa19046fc..2b163d74a0260 100644 --- a/tests/baselines/reference/indexingTypesWithNever.symbols +++ b/tests/baselines/reference/indexingTypesWithNever.symbols @@ -93,283 +93,297 @@ const result5 = genericFn3({ g: "gtest", h: "htest" }, "g", "h"); // 'g' & 'h' w >g : Symbol(g, Decl(indexingTypesWithNever.ts, 32, 28)) >h : Symbol(h, Decl(indexingTypesWithNever.ts, 32, 40)) + +declare const obj: {a: string, b: number} +>obj : Symbol(obj, Decl(indexingTypesWithNever.ts, 35, 13)) +>a : Symbol(a, Decl(indexingTypesWithNever.ts, 35, 20)) +>b : Symbol(b, Decl(indexingTypesWithNever.ts, 35, 30)) + +declare const key: never +>key : Symbol(key, Decl(indexingTypesWithNever.ts, 36, 13)) + +const result6 = obj[key] +>result6 : Symbol(result6, Decl(indexingTypesWithNever.ts, 38, 5)) +>obj : Symbol(obj, Decl(indexingTypesWithNever.ts, 35, 13)) +>key : Symbol(key, Decl(indexingTypesWithNever.ts, 36, 13)) + // Expanded examples from https://github.com/Microsoft/TypeScript/issues/21988 type RequiredPropNames = { ->RequiredPropNames : Symbol(RequiredPropNames, Decl(indexingTypesWithNever.ts, 32, 65)) ->T : Symbol(T, Decl(indexingTypesWithNever.ts, 35, 23)) +>RequiredPropNames : Symbol(RequiredPropNames, Decl(indexingTypesWithNever.ts, 38, 24)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 41, 23)) [P in keyof T]-?: undefined extends T[P] ? never : P ->P : Symbol(P, Decl(indexingTypesWithNever.ts, 36, 3)) ->T : Symbol(T, Decl(indexingTypesWithNever.ts, 35, 23)) ->T : Symbol(T, Decl(indexingTypesWithNever.ts, 35, 23)) ->P : Symbol(P, Decl(indexingTypesWithNever.ts, 36, 3)) ->P : Symbol(P, Decl(indexingTypesWithNever.ts, 36, 3)) +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 42, 3)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 41, 23)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 41, 23)) +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 42, 3)) +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 42, 3)) }[keyof T]; ->T : Symbol(T, Decl(indexingTypesWithNever.ts, 35, 23)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 41, 23)) type OptionalPropNames = { ->OptionalPropNames : Symbol(OptionalPropNames, Decl(indexingTypesWithNever.ts, 37, 11)) ->T : Symbol(T, Decl(indexingTypesWithNever.ts, 39, 23)) +>OptionalPropNames : Symbol(OptionalPropNames, Decl(indexingTypesWithNever.ts, 43, 11)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 45, 23)) [P in keyof T]-?: undefined extends T[P] ? P : never ->P : Symbol(P, Decl(indexingTypesWithNever.ts, 40, 3)) ->T : Symbol(T, Decl(indexingTypesWithNever.ts, 39, 23)) ->T : Symbol(T, Decl(indexingTypesWithNever.ts, 39, 23)) ->P : Symbol(P, Decl(indexingTypesWithNever.ts, 40, 3)) ->P : Symbol(P, Decl(indexingTypesWithNever.ts, 40, 3)) +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 46, 3)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 45, 23)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 45, 23)) +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 46, 3)) +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 46, 3)) }[keyof T]; ->T : Symbol(T, Decl(indexingTypesWithNever.ts, 39, 23)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 45, 23)) type RequiredProps = { [P in RequiredPropNames]: T[P] }; ->RequiredProps : Symbol(RequiredProps, Decl(indexingTypesWithNever.ts, 41, 11)) ->T : Symbol(T, Decl(indexingTypesWithNever.ts, 43, 19)) ->P : Symbol(P, Decl(indexingTypesWithNever.ts, 43, 27)) ->RequiredPropNames : Symbol(RequiredPropNames, Decl(indexingTypesWithNever.ts, 32, 65)) ->T : Symbol(T, Decl(indexingTypesWithNever.ts, 43, 19)) ->T : Symbol(T, Decl(indexingTypesWithNever.ts, 43, 19)) ->P : Symbol(P, Decl(indexingTypesWithNever.ts, 43, 27)) +>RequiredProps : Symbol(RequiredProps, Decl(indexingTypesWithNever.ts, 47, 11)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 49, 19)) +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 49, 27)) +>RequiredPropNames : Symbol(RequiredPropNames, Decl(indexingTypesWithNever.ts, 38, 24)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 49, 19)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 49, 19)) +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 49, 27)) type OptionalProps = { [P in OptionalPropNames]?: T[P] }; ->OptionalProps : Symbol(OptionalProps, Decl(indexingTypesWithNever.ts, 43, 62)) ->T : Symbol(T, Decl(indexingTypesWithNever.ts, 44, 19)) ->P : Symbol(P, Decl(indexingTypesWithNever.ts, 44, 27)) ->OptionalPropNames : Symbol(OptionalPropNames, Decl(indexingTypesWithNever.ts, 37, 11)) ->T : Symbol(T, Decl(indexingTypesWithNever.ts, 44, 19)) ->T : Symbol(T, Decl(indexingTypesWithNever.ts, 44, 19)) ->P : Symbol(P, Decl(indexingTypesWithNever.ts, 44, 27)) +>OptionalProps : Symbol(OptionalProps, Decl(indexingTypesWithNever.ts, 49, 62)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 50, 19)) +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 50, 27)) +>OptionalPropNames : Symbol(OptionalPropNames, Decl(indexingTypesWithNever.ts, 43, 11)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 50, 19)) +>T : Symbol(T, Decl(indexingTypesWithNever.ts, 50, 19)) +>P : Symbol(P, Decl(indexingTypesWithNever.ts, 50, 27)) type Match = [Exp] extends [Act] ->Match : Symbol(Match, Decl(indexingTypesWithNever.ts, 44, 63)) ->Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 46, 11)) ->Act : Symbol(Act, Decl(indexingTypesWithNever.ts, 46, 15)) ->Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 46, 11)) ->Act : Symbol(Act, Decl(indexingTypesWithNever.ts, 46, 15)) +>Match : Symbol(Match, Decl(indexingTypesWithNever.ts, 50, 63)) +>Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 52, 11)) +>Act : Symbol(Act, Decl(indexingTypesWithNever.ts, 52, 15)) +>Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 52, 11)) +>Act : Symbol(Act, Decl(indexingTypesWithNever.ts, 52, 15)) ? ([Act] extends [Exp] ? "Match" : "Did not match 2") ->Act : Symbol(Act, Decl(indexingTypesWithNever.ts, 46, 15)) ->Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 46, 11)) +>Act : Symbol(Act, Decl(indexingTypesWithNever.ts, 52, 15)) +>Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 52, 11)) : "Did not match 1"; type ExpectType = Match extends "Match" ->ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) ->Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 50, 16)) ->Act : Symbol(Act, Decl(indexingTypesWithNever.ts, 50, 20)) ->Match : Symbol(Match, Decl(indexingTypesWithNever.ts, 44, 63)) ->Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 50, 16)) ->Act : Symbol(Act, Decl(indexingTypesWithNever.ts, 50, 20)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 54, 22)) +>Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 56, 16)) +>Act : Symbol(Act, Decl(indexingTypesWithNever.ts, 56, 20)) +>Match : Symbol(Match, Decl(indexingTypesWithNever.ts, 50, 63)) +>Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 56, 16)) +>Act : Symbol(Act, Decl(indexingTypesWithNever.ts, 56, 20)) ? ({} extends Exp ? Match, Required> : "Match") ->Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 50, 16)) ->Match : Symbol(Match, Decl(indexingTypesWithNever.ts, 44, 63)) +>Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 56, 16)) +>Match : Symbol(Match, Decl(indexingTypesWithNever.ts, 50, 63)) >Required : Symbol(Required, Decl(lib.d.ts, --, --)) ->Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 50, 16)) +>Exp : Symbol(Exp, Decl(indexingTypesWithNever.ts, 56, 16)) >Required : Symbol(Required, Decl(lib.d.ts, --, --)) ->Act : Symbol(Act, Decl(indexingTypesWithNever.ts, 50, 20)) +>Act : Symbol(Act, Decl(indexingTypesWithNever.ts, 56, 20)) : "Did not match"; type P3 = { a: string; b: number; c?: boolean }; ->P3 : Symbol(P3, Decl(indexingTypesWithNever.ts, 52, 20)) ->a : Symbol(a, Decl(indexingTypesWithNever.ts, 54, 11)) ->b : Symbol(b, Decl(indexingTypesWithNever.ts, 54, 22)) ->c : Symbol(c, Decl(indexingTypesWithNever.ts, 54, 33)) +>P3 : Symbol(P3, Decl(indexingTypesWithNever.ts, 58, 20)) +>a : Symbol(a, Decl(indexingTypesWithNever.ts, 60, 11)) +>b : Symbol(b, Decl(indexingTypesWithNever.ts, 60, 22)) +>c : Symbol(c, Decl(indexingTypesWithNever.ts, 60, 33)) type P2 = { a: string; c?: boolean }; ->P2 : Symbol(P2, Decl(indexingTypesWithNever.ts, 54, 48)) ->a : Symbol(a, Decl(indexingTypesWithNever.ts, 55, 11)) ->c : Symbol(c, Decl(indexingTypesWithNever.ts, 55, 22)) +>P2 : Symbol(P2, Decl(indexingTypesWithNever.ts, 60, 48)) +>a : Symbol(a, Decl(indexingTypesWithNever.ts, 61, 11)) +>c : Symbol(c, Decl(indexingTypesWithNever.ts, 61, 22)) type P1 = { c?: boolean }; ->P1 : Symbol(P1, Decl(indexingTypesWithNever.ts, 55, 37)) ->c : Symbol(c, Decl(indexingTypesWithNever.ts, 56, 11)) +>P1 : Symbol(P1, Decl(indexingTypesWithNever.ts, 61, 37)) +>c : Symbol(c, Decl(indexingTypesWithNever.ts, 62, 11)) type P0 = {}; ->P0 : Symbol(P0, Decl(indexingTypesWithNever.ts, 56, 26)) +>P0 : Symbol(P0, Decl(indexingTypesWithNever.ts, 62, 26)) type P3Names = RequiredPropNames; // expect 'a' | 'b' ->P3Names : Symbol(P3Names, Decl(indexingTypesWithNever.ts, 57, 13)) ->RequiredPropNames : Symbol(RequiredPropNames, Decl(indexingTypesWithNever.ts, 32, 65)) ->P3 : Symbol(P3, Decl(indexingTypesWithNever.ts, 52, 20)) +>P3Names : Symbol(P3Names, Decl(indexingTypesWithNever.ts, 63, 13)) +>RequiredPropNames : Symbol(RequiredPropNames, Decl(indexingTypesWithNever.ts, 38, 24)) +>P3 : Symbol(P3, Decl(indexingTypesWithNever.ts, 58, 20)) type P2Names = RequiredPropNames; // expect 'a' ->P2Names : Symbol(P2Names, Decl(indexingTypesWithNever.ts, 59, 37)) ->RequiredPropNames : Symbol(RequiredPropNames, Decl(indexingTypesWithNever.ts, 32, 65)) ->P2 : Symbol(P2, Decl(indexingTypesWithNever.ts, 54, 48)) +>P2Names : Symbol(P2Names, Decl(indexingTypesWithNever.ts, 65, 37)) +>RequiredPropNames : Symbol(RequiredPropNames, Decl(indexingTypesWithNever.ts, 38, 24)) +>P2 : Symbol(P2, Decl(indexingTypesWithNever.ts, 60, 48)) type P1Names = RequiredPropNames; // expect never ->P1Names : Symbol(P1Names, Decl(indexingTypesWithNever.ts, 60, 37)) ->RequiredPropNames : Symbol(RequiredPropNames, Decl(indexingTypesWithNever.ts, 32, 65)) ->P1 : Symbol(P1, Decl(indexingTypesWithNever.ts, 55, 37)) +>P1Names : Symbol(P1Names, Decl(indexingTypesWithNever.ts, 66, 37)) +>RequiredPropNames : Symbol(RequiredPropNames, Decl(indexingTypesWithNever.ts, 38, 24)) +>P1 : Symbol(P1, Decl(indexingTypesWithNever.ts, 61, 37)) type P0Names = RequiredPropNames; // expect never ->P0Names : Symbol(P0Names, Decl(indexingTypesWithNever.ts, 61, 37)) ->RequiredPropNames : Symbol(RequiredPropNames, Decl(indexingTypesWithNever.ts, 32, 65)) ->P0 : Symbol(P0, Decl(indexingTypesWithNever.ts, 56, 26)) +>P0Names : Symbol(P0Names, Decl(indexingTypesWithNever.ts, 67, 37)) +>RequiredPropNames : Symbol(RequiredPropNames, Decl(indexingTypesWithNever.ts, 38, 24)) +>P0 : Symbol(P0, Decl(indexingTypesWithNever.ts, 62, 26)) declare const p3NameTest: ExpectType<"a" | "b", P3Names>; ->p3NameTest : Symbol(p3NameTest, Decl(indexingTypesWithNever.ts, 64, 13)) ->ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) ->P3Names : Symbol(P3Names, Decl(indexingTypesWithNever.ts, 57, 13)) +>p3NameTest : Symbol(p3NameTest, Decl(indexingTypesWithNever.ts, 70, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 54, 22)) +>P3Names : Symbol(P3Names, Decl(indexingTypesWithNever.ts, 63, 13)) declare const p2NameTest: ExpectType<"a", P2Names>; ->p2NameTest : Symbol(p2NameTest, Decl(indexingTypesWithNever.ts, 65, 13)) ->ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) ->P2Names : Symbol(P2Names, Decl(indexingTypesWithNever.ts, 59, 37)) +>p2NameTest : Symbol(p2NameTest, Decl(indexingTypesWithNever.ts, 71, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 54, 22)) +>P2Names : Symbol(P2Names, Decl(indexingTypesWithNever.ts, 65, 37)) declare const p1NameTest: ExpectType; ->p1NameTest : Symbol(p1NameTest, Decl(indexingTypesWithNever.ts, 66, 13)) ->ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) ->P1Names : Symbol(P1Names, Decl(indexingTypesWithNever.ts, 60, 37)) +>p1NameTest : Symbol(p1NameTest, Decl(indexingTypesWithNever.ts, 72, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 54, 22)) +>P1Names : Symbol(P1Names, Decl(indexingTypesWithNever.ts, 66, 37)) declare const p0NameTest: ExpectType; ->p0NameTest : Symbol(p0NameTest, Decl(indexingTypesWithNever.ts, 67, 13)) ->ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) ->P0Names : Symbol(P0Names, Decl(indexingTypesWithNever.ts, 61, 37)) +>p0NameTest : Symbol(p0NameTest, Decl(indexingTypesWithNever.ts, 73, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 54, 22)) +>P0Names : Symbol(P0Names, Decl(indexingTypesWithNever.ts, 67, 37)) type P3Props = RequiredProps; // expect { a: string; b: number } ->P3Props : Symbol(P3Props, Decl(indexingTypesWithNever.ts, 67, 53)) ->RequiredProps : Symbol(RequiredProps, Decl(indexingTypesWithNever.ts, 41, 11)) ->P3 : Symbol(P3, Decl(indexingTypesWithNever.ts, 52, 20)) +>P3Props : Symbol(P3Props, Decl(indexingTypesWithNever.ts, 73, 53)) +>RequiredProps : Symbol(RequiredProps, Decl(indexingTypesWithNever.ts, 47, 11)) +>P3 : Symbol(P3, Decl(indexingTypesWithNever.ts, 58, 20)) type P2Props = RequiredProps; // expect { a: string; } ->P2Props : Symbol(P2Props, Decl(indexingTypesWithNever.ts, 69, 33)) ->RequiredProps : Symbol(RequiredProps, Decl(indexingTypesWithNever.ts, 41, 11)) ->P2 : Symbol(P2, Decl(indexingTypesWithNever.ts, 54, 48)) +>P2Props : Symbol(P2Props, Decl(indexingTypesWithNever.ts, 75, 33)) +>RequiredProps : Symbol(RequiredProps, Decl(indexingTypesWithNever.ts, 47, 11)) +>P2 : Symbol(P2, Decl(indexingTypesWithNever.ts, 60, 48)) type P1Props = RequiredProps; // expect {} ->P1Props : Symbol(P1Props, Decl(indexingTypesWithNever.ts, 70, 33)) ->RequiredProps : Symbol(RequiredProps, Decl(indexingTypesWithNever.ts, 41, 11)) ->P1 : Symbol(P1, Decl(indexingTypesWithNever.ts, 55, 37)) +>P1Props : Symbol(P1Props, Decl(indexingTypesWithNever.ts, 76, 33)) +>RequiredProps : Symbol(RequiredProps, Decl(indexingTypesWithNever.ts, 47, 11)) +>P1 : Symbol(P1, Decl(indexingTypesWithNever.ts, 61, 37)) type P0Props = RequiredProps; // expect {} ->P0Props : Symbol(P0Props, Decl(indexingTypesWithNever.ts, 71, 33)) ->RequiredProps : Symbol(RequiredProps, Decl(indexingTypesWithNever.ts, 41, 11)) ->P0 : Symbol(P0, Decl(indexingTypesWithNever.ts, 56, 26)) +>P0Props : Symbol(P0Props, Decl(indexingTypesWithNever.ts, 77, 33)) +>RequiredProps : Symbol(RequiredProps, Decl(indexingTypesWithNever.ts, 47, 11)) +>P0 : Symbol(P0, Decl(indexingTypesWithNever.ts, 62, 26)) declare const p3Test: ExpectType<{ a: string; b: number }, P3Props>; ->p3Test : Symbol(p3Test, Decl(indexingTypesWithNever.ts, 74, 13)) ->ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) ->a : Symbol(a, Decl(indexingTypesWithNever.ts, 74, 34)) ->b : Symbol(b, Decl(indexingTypesWithNever.ts, 74, 45)) ->P3Props : Symbol(P3Props, Decl(indexingTypesWithNever.ts, 67, 53)) +>p3Test : Symbol(p3Test, Decl(indexingTypesWithNever.ts, 80, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 54, 22)) +>a : Symbol(a, Decl(indexingTypesWithNever.ts, 80, 34)) +>b : Symbol(b, Decl(indexingTypesWithNever.ts, 80, 45)) +>P3Props : Symbol(P3Props, Decl(indexingTypesWithNever.ts, 73, 53)) declare const p2Test: ExpectType<{ a: string }, P2Props>; ->p2Test : Symbol(p2Test, Decl(indexingTypesWithNever.ts, 75, 13)) ->ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) ->a : Symbol(a, Decl(indexingTypesWithNever.ts, 75, 34)) ->P2Props : Symbol(P2Props, Decl(indexingTypesWithNever.ts, 69, 33)) +>p2Test : Symbol(p2Test, Decl(indexingTypesWithNever.ts, 81, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 54, 22)) +>a : Symbol(a, Decl(indexingTypesWithNever.ts, 81, 34)) +>P2Props : Symbol(P2Props, Decl(indexingTypesWithNever.ts, 75, 33)) declare const p1Test: ExpectType<{}, P1Props>; ->p1Test : Symbol(p1Test, Decl(indexingTypesWithNever.ts, 76, 13)) ->ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) ->P1Props : Symbol(P1Props, Decl(indexingTypesWithNever.ts, 70, 33)) +>p1Test : Symbol(p1Test, Decl(indexingTypesWithNever.ts, 82, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 54, 22)) +>P1Props : Symbol(P1Props, Decl(indexingTypesWithNever.ts, 76, 33)) declare const p0Test: ExpectType<{}, P0Props>; ->p0Test : Symbol(p0Test, Decl(indexingTypesWithNever.ts, 77, 13)) ->ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) ->P0Props : Symbol(P0Props, Decl(indexingTypesWithNever.ts, 71, 33)) +>p0Test : Symbol(p0Test, Decl(indexingTypesWithNever.ts, 83, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 54, 22)) +>P0Props : Symbol(P0Props, Decl(indexingTypesWithNever.ts, 77, 33)) type O3 = { a?: string; b?: number; c: boolean }; ->O3 : Symbol(O3, Decl(indexingTypesWithNever.ts, 77, 46)) ->a : Symbol(a, Decl(indexingTypesWithNever.ts, 79, 11)) ->b : Symbol(b, Decl(indexingTypesWithNever.ts, 79, 23)) ->c : Symbol(c, Decl(indexingTypesWithNever.ts, 79, 35)) +>O3 : Symbol(O3, Decl(indexingTypesWithNever.ts, 83, 46)) +>a : Symbol(a, Decl(indexingTypesWithNever.ts, 85, 11)) +>b : Symbol(b, Decl(indexingTypesWithNever.ts, 85, 23)) +>c : Symbol(c, Decl(indexingTypesWithNever.ts, 85, 35)) type O2 = { a?: string; c: boolean }; ->O2 : Symbol(O2, Decl(indexingTypesWithNever.ts, 79, 49)) ->a : Symbol(a, Decl(indexingTypesWithNever.ts, 80, 11)) ->c : Symbol(c, Decl(indexingTypesWithNever.ts, 80, 23)) +>O2 : Symbol(O2, Decl(indexingTypesWithNever.ts, 85, 49)) +>a : Symbol(a, Decl(indexingTypesWithNever.ts, 86, 11)) +>c : Symbol(c, Decl(indexingTypesWithNever.ts, 86, 23)) type O1 = { c: boolean }; ->O1 : Symbol(O1, Decl(indexingTypesWithNever.ts, 80, 37)) ->c : Symbol(c, Decl(indexingTypesWithNever.ts, 81, 11)) +>O1 : Symbol(O1, Decl(indexingTypesWithNever.ts, 86, 37)) +>c : Symbol(c, Decl(indexingTypesWithNever.ts, 87, 11)) type O0 = {}; ->O0 : Symbol(O0, Decl(indexingTypesWithNever.ts, 81, 25)) +>O0 : Symbol(O0, Decl(indexingTypesWithNever.ts, 87, 25)) type O3Names = OptionalPropNames; // expect 'a' | 'b' ->O3Names : Symbol(O3Names, Decl(indexingTypesWithNever.ts, 82, 13)) ->OptionalPropNames : Symbol(OptionalPropNames, Decl(indexingTypesWithNever.ts, 37, 11)) ->O3 : Symbol(O3, Decl(indexingTypesWithNever.ts, 77, 46)) +>O3Names : Symbol(O3Names, Decl(indexingTypesWithNever.ts, 88, 13)) +>OptionalPropNames : Symbol(OptionalPropNames, Decl(indexingTypesWithNever.ts, 43, 11)) +>O3 : Symbol(O3, Decl(indexingTypesWithNever.ts, 83, 46)) type O2Names = OptionalPropNames; // expect 'a' ->O2Names : Symbol(O2Names, Decl(indexingTypesWithNever.ts, 84, 37)) ->OptionalPropNames : Symbol(OptionalPropNames, Decl(indexingTypesWithNever.ts, 37, 11)) ->O2 : Symbol(O2, Decl(indexingTypesWithNever.ts, 79, 49)) +>O2Names : Symbol(O2Names, Decl(indexingTypesWithNever.ts, 90, 37)) +>OptionalPropNames : Symbol(OptionalPropNames, Decl(indexingTypesWithNever.ts, 43, 11)) +>O2 : Symbol(O2, Decl(indexingTypesWithNever.ts, 85, 49)) type O1Names = OptionalPropNames; // expect never ->O1Names : Symbol(O1Names, Decl(indexingTypesWithNever.ts, 85, 37)) ->OptionalPropNames : Symbol(OptionalPropNames, Decl(indexingTypesWithNever.ts, 37, 11)) ->O1 : Symbol(O1, Decl(indexingTypesWithNever.ts, 80, 37)) +>O1Names : Symbol(O1Names, Decl(indexingTypesWithNever.ts, 91, 37)) +>OptionalPropNames : Symbol(OptionalPropNames, Decl(indexingTypesWithNever.ts, 43, 11)) +>O1 : Symbol(O1, Decl(indexingTypesWithNever.ts, 86, 37)) type O0Names = OptionalPropNames; // expect never ->O0Names : Symbol(O0Names, Decl(indexingTypesWithNever.ts, 86, 37)) ->OptionalPropNames : Symbol(OptionalPropNames, Decl(indexingTypesWithNever.ts, 37, 11)) ->O0 : Symbol(O0, Decl(indexingTypesWithNever.ts, 81, 25)) +>O0Names : Symbol(O0Names, Decl(indexingTypesWithNever.ts, 92, 37)) +>OptionalPropNames : Symbol(OptionalPropNames, Decl(indexingTypesWithNever.ts, 43, 11)) +>O0 : Symbol(O0, Decl(indexingTypesWithNever.ts, 87, 25)) declare const o3NameTest: ExpectType<"a" | "b", O3Names>; ->o3NameTest : Symbol(o3NameTest, Decl(indexingTypesWithNever.ts, 89, 13)) ->ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) ->O3Names : Symbol(O3Names, Decl(indexingTypesWithNever.ts, 82, 13)) +>o3NameTest : Symbol(o3NameTest, Decl(indexingTypesWithNever.ts, 95, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 54, 22)) +>O3Names : Symbol(O3Names, Decl(indexingTypesWithNever.ts, 88, 13)) declare const o2NameTest: ExpectType<"a", O2Names>; ->o2NameTest : Symbol(o2NameTest, Decl(indexingTypesWithNever.ts, 90, 13)) ->ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) ->O2Names : Symbol(O2Names, Decl(indexingTypesWithNever.ts, 84, 37)) +>o2NameTest : Symbol(o2NameTest, Decl(indexingTypesWithNever.ts, 96, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 54, 22)) +>O2Names : Symbol(O2Names, Decl(indexingTypesWithNever.ts, 90, 37)) declare const o1NameTest: ExpectType; ->o1NameTest : Symbol(o1NameTest, Decl(indexingTypesWithNever.ts, 91, 13)) ->ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) ->O1Names : Symbol(O1Names, Decl(indexingTypesWithNever.ts, 85, 37)) +>o1NameTest : Symbol(o1NameTest, Decl(indexingTypesWithNever.ts, 97, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 54, 22)) +>O1Names : Symbol(O1Names, Decl(indexingTypesWithNever.ts, 91, 37)) declare const o0NameTest: ExpectType; ->o0NameTest : Symbol(o0NameTest, Decl(indexingTypesWithNever.ts, 92, 13)) ->ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) ->O0Names : Symbol(O0Names, Decl(indexingTypesWithNever.ts, 86, 37)) +>o0NameTest : Symbol(o0NameTest, Decl(indexingTypesWithNever.ts, 98, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 54, 22)) +>O0Names : Symbol(O0Names, Decl(indexingTypesWithNever.ts, 92, 37)) type O3Props = OptionalProps; // expect { a?: string | undefined; b?: number | undefined } ->O3Props : Symbol(O3Props, Decl(indexingTypesWithNever.ts, 92, 53)) ->OptionalProps : Symbol(OptionalProps, Decl(indexingTypesWithNever.ts, 43, 62)) ->O3 : Symbol(O3, Decl(indexingTypesWithNever.ts, 77, 46)) +>O3Props : Symbol(O3Props, Decl(indexingTypesWithNever.ts, 98, 53)) +>OptionalProps : Symbol(OptionalProps, Decl(indexingTypesWithNever.ts, 49, 62)) +>O3 : Symbol(O3, Decl(indexingTypesWithNever.ts, 83, 46)) type O2Props = OptionalProps; // expect { a?: string | undefined; } ->O2Props : Symbol(O2Props, Decl(indexingTypesWithNever.ts, 94, 33)) ->OptionalProps : Symbol(OptionalProps, Decl(indexingTypesWithNever.ts, 43, 62)) ->O2 : Symbol(O2, Decl(indexingTypesWithNever.ts, 79, 49)) +>O2Props : Symbol(O2Props, Decl(indexingTypesWithNever.ts, 100, 33)) +>OptionalProps : Symbol(OptionalProps, Decl(indexingTypesWithNever.ts, 49, 62)) +>O2 : Symbol(O2, Decl(indexingTypesWithNever.ts, 85, 49)) type O1Props = OptionalProps; // expect {} ->O1Props : Symbol(O1Props, Decl(indexingTypesWithNever.ts, 95, 33)) ->OptionalProps : Symbol(OptionalProps, Decl(indexingTypesWithNever.ts, 43, 62)) ->O1 : Symbol(O1, Decl(indexingTypesWithNever.ts, 80, 37)) +>O1Props : Symbol(O1Props, Decl(indexingTypesWithNever.ts, 101, 33)) +>OptionalProps : Symbol(OptionalProps, Decl(indexingTypesWithNever.ts, 49, 62)) +>O1 : Symbol(O1, Decl(indexingTypesWithNever.ts, 86, 37)) type O0Props = OptionalProps; // expect {} ->O0Props : Symbol(O0Props, Decl(indexingTypesWithNever.ts, 96, 33)) ->OptionalProps : Symbol(OptionalProps, Decl(indexingTypesWithNever.ts, 43, 62)) ->O0 : Symbol(O0, Decl(indexingTypesWithNever.ts, 81, 25)) +>O0Props : Symbol(O0Props, Decl(indexingTypesWithNever.ts, 102, 33)) +>OptionalProps : Symbol(OptionalProps, Decl(indexingTypesWithNever.ts, 49, 62)) +>O0 : Symbol(O0, Decl(indexingTypesWithNever.ts, 87, 25)) declare const o3Test: ExpectType<{ a?: string; b?: number }, O3Props>; ->o3Test : Symbol(o3Test, Decl(indexingTypesWithNever.ts, 99, 13)) ->ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) ->a : Symbol(a, Decl(indexingTypesWithNever.ts, 99, 34)) ->b : Symbol(b, Decl(indexingTypesWithNever.ts, 99, 46)) ->O3Props : Symbol(O3Props, Decl(indexingTypesWithNever.ts, 92, 53)) +>o3Test : Symbol(o3Test, Decl(indexingTypesWithNever.ts, 105, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 54, 22)) +>a : Symbol(a, Decl(indexingTypesWithNever.ts, 105, 34)) +>b : Symbol(b, Decl(indexingTypesWithNever.ts, 105, 46)) +>O3Props : Symbol(O3Props, Decl(indexingTypesWithNever.ts, 98, 53)) declare const o2Test: ExpectType<{ a?: string }, O2Props>; ->o2Test : Symbol(o2Test, Decl(indexingTypesWithNever.ts, 100, 13)) ->ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) ->a : Symbol(a, Decl(indexingTypesWithNever.ts, 100, 34)) ->O2Props : Symbol(O2Props, Decl(indexingTypesWithNever.ts, 94, 33)) +>o2Test : Symbol(o2Test, Decl(indexingTypesWithNever.ts, 106, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 54, 22)) +>a : Symbol(a, Decl(indexingTypesWithNever.ts, 106, 34)) +>O2Props : Symbol(O2Props, Decl(indexingTypesWithNever.ts, 100, 33)) declare const o1Test: ExpectType<{}, O1Props>; ->o1Test : Symbol(o1Test, Decl(indexingTypesWithNever.ts, 101, 13)) ->ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) ->O1Props : Symbol(O1Props, Decl(indexingTypesWithNever.ts, 95, 33)) +>o1Test : Symbol(o1Test, Decl(indexingTypesWithNever.ts, 107, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 54, 22)) +>O1Props : Symbol(O1Props, Decl(indexingTypesWithNever.ts, 101, 33)) declare const o0Test: ExpectType<{}, O0Props>; ->o0Test : Symbol(o0Test, Decl(indexingTypesWithNever.ts, 102, 13)) ->ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 48, 22)) ->O0Props : Symbol(O0Props, Decl(indexingTypesWithNever.ts, 96, 33)) +>o0Test : Symbol(o0Test, Decl(indexingTypesWithNever.ts, 108, 13)) +>ExpectType : Symbol(ExpectType, Decl(indexingTypesWithNever.ts, 54, 22)) +>O0Props : Symbol(O0Props, Decl(indexingTypesWithNever.ts, 102, 33)) diff --git a/tests/baselines/reference/indexingTypesWithNever.types b/tests/baselines/reference/indexingTypesWithNever.types index 733fd875d4fe9..4ec24ed772abb 100644 --- a/tests/baselines/reference/indexingTypesWithNever.types +++ b/tests/baselines/reference/indexingTypesWithNever.types @@ -107,6 +107,21 @@ const result5 = genericFn3({ g: "gtest", h: "htest" }, "g", "h"); // 'g' & 'h' w >"g" : "g" >"h" : "h" + +declare const obj: {a: string, b: number} +>obj : { a: string; b: number; } +>a : string +>b : number + +declare const key: never +>key : never + +const result6 = obj[key] +>result6 : any +>obj[key] : any +>obj : { a: string; b: number; } +>key : never + // Expanded examples from https://github.com/Microsoft/TypeScript/issues/21988 type RequiredPropNames = { >RequiredPropNames : { [P in keyof T]-?: undefined extends T[P] ? never : P; }[keyof T] diff --git a/tests/cases/compiler/indexingTypesWithNever.ts b/tests/cases/compiler/indexingTypesWithNever.ts index 467b74eafc67f..9044ded2ff4c3 100644 --- a/tests/cases/compiler/indexingTypesWithNever.ts +++ b/tests/cases/compiler/indexingTypesWithNever.ts @@ -34,6 +34,12 @@ declare function genericFn3< // Should be never const result5 = genericFn3({ g: "gtest", h: "htest" }, "g", "h"); // 'g' & 'h' will reduce to never + +declare const obj: {a: string, b: number} +declare const key: never + +const result6 = obj[key] + // Expanded examples from https://github.com/Microsoft/TypeScript/issues/21988 type RequiredPropNames = { [P in keyof T]-?: undefined extends T[P] ? never : P From 5d19c691615be79fe19ec107d47c985719df5f61 Mon Sep 17 00:00:00 2001 From: Kevin Donnelly Date: Mon, 26 Mar 2018 19:20:22 -0500 Subject: [PATCH 4/4] Make indexing an object with never expression result in never. And update baseline to reflect new behavior. --- src/compiler/checker.ts | 6 +- .../indexingTypesWithNever.errors.txt | 116 ------------------ .../reference/indexingTypesWithNever.types | 4 +- 3 files changed, 5 insertions(+), 121 deletions(-) delete mode 100644 tests/baselines/reference/indexingTypesWithNever.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d4c5a5695dd2c..cc17e30e0e098 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8151,6 +8151,9 @@ namespace ts { } return indexInfo.type; } + if (indexType.flags & TypeFlags.Never) { + return neverType; + } if (accessExpression && !isConstEnumObjectType(objectType)) { if (noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors) { if (getIndexTypeOfType(objectType, IndexKind.Number)) { @@ -8163,9 +8166,6 @@ namespace ts { return anyType; } } - if (indexType.flags & TypeFlags.Never) { - return neverType; - } if (accessNode) { const indexNode = accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode.argumentExpression : accessNode.indexType; if (indexType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) { diff --git a/tests/baselines/reference/indexingTypesWithNever.errors.txt b/tests/baselines/reference/indexingTypesWithNever.errors.txt deleted file mode 100644 index 713a24e816f72..0000000000000 --- a/tests/baselines/reference/indexingTypesWithNever.errors.txt +++ /dev/null @@ -1,116 +0,0 @@ -tests/cases/compiler/indexingTypesWithNever.ts(39,17): error TS7017: Element implicitly has an 'any' type because type '{ a: string; b: number; }' has no index signature. - - -==== tests/cases/compiler/indexingTypesWithNever.ts (1 errors) ==== - type TestObj = { - a: string; - b: number; - }; - - // Should be never but without an error - type Result1 = TestObj[never]; - - type EmptyObj = {}; - - // Should be never but without an error - type Result2 = EmptyObj[keyof EmptyObj]; - - declare function genericFn1(obj: T): T[never]; - - // Should be never - const result3 = genericFn1({ c: "ctest", d: "dtest" }); - - declare function genericFn2( - obj: T - ): T[never]; - - // Should be never - const result4 = genericFn2({ e: "etest", f: "ftest" }); - - declare function genericFn3< - T extends { [K in keyof T]: T[K] }, - U extends keyof T, - V extends keyof T - >(obj: T, u: U, v: V): T[U & V]; - - // Should be never - const result5 = genericFn3({ g: "gtest", h: "htest" }, "g", "h"); // 'g' & 'h' will reduce to never - - - declare const obj: {a: string, b: number} - declare const key: never - - const result6 = obj[key] - ~~~~~~~~ -!!! error TS7017: Element implicitly has an 'any' type because type '{ a: string; b: number; }' has no index signature. - - // Expanded examples from https://github.com/Microsoft/TypeScript/issues/21988 - type RequiredPropNames = { - [P in keyof T]-?: undefined extends T[P] ? never : P - }[keyof T]; - - type OptionalPropNames = { - [P in keyof T]-?: undefined extends T[P] ? P : never - }[keyof T]; - - type RequiredProps = { [P in RequiredPropNames]: T[P] }; - type OptionalProps = { [P in OptionalPropNames]?: T[P] }; - - type Match = [Exp] extends [Act] - ? ([Act] extends [Exp] ? "Match" : "Did not match 2") - : "Did not match 1"; - - type ExpectType = Match extends "Match" - ? ({} extends Exp ? Match, Required> : "Match") - : "Did not match"; - - type P3 = { a: string; b: number; c?: boolean }; - type P2 = { a: string; c?: boolean }; - type P1 = { c?: boolean }; - type P0 = {}; - - type P3Names = RequiredPropNames; // expect 'a' | 'b' - type P2Names = RequiredPropNames; // expect 'a' - type P1Names = RequiredPropNames; // expect never - type P0Names = RequiredPropNames; // expect never - - declare const p3NameTest: ExpectType<"a" | "b", P3Names>; - declare const p2NameTest: ExpectType<"a", P2Names>; - declare const p1NameTest: ExpectType; - declare const p0NameTest: ExpectType; - - type P3Props = RequiredProps; // expect { a: string; b: number } - type P2Props = RequiredProps; // expect { a: string; } - type P1Props = RequiredProps; // expect {} - type P0Props = RequiredProps; // expect {} - - declare const p3Test: ExpectType<{ a: string; b: number }, P3Props>; - declare const p2Test: ExpectType<{ a: string }, P2Props>; - declare const p1Test: ExpectType<{}, P1Props>; - declare const p0Test: ExpectType<{}, P0Props>; - - type O3 = { a?: string; b?: number; c: boolean }; - type O2 = { a?: string; c: boolean }; - type O1 = { c: boolean }; - type O0 = {}; - - type O3Names = OptionalPropNames; // expect 'a' | 'b' - type O2Names = OptionalPropNames; // expect 'a' - type O1Names = OptionalPropNames; // expect never - type O0Names = OptionalPropNames; // expect never - - declare const o3NameTest: ExpectType<"a" | "b", O3Names>; - declare const o2NameTest: ExpectType<"a", O2Names>; - declare const o1NameTest: ExpectType; - declare const o0NameTest: ExpectType; - - type O3Props = OptionalProps; // expect { a?: string | undefined; b?: number | undefined } - type O2Props = OptionalProps; // expect { a?: string | undefined; } - type O1Props = OptionalProps; // expect {} - type O0Props = OptionalProps; // expect {} - - declare const o3Test: ExpectType<{ a?: string; b?: number }, O3Props>; - declare const o2Test: ExpectType<{ a?: string }, O2Props>; - declare const o1Test: ExpectType<{}, O1Props>; - declare const o0Test: ExpectType<{}, O0Props>; - \ No newline at end of file diff --git a/tests/baselines/reference/indexingTypesWithNever.types b/tests/baselines/reference/indexingTypesWithNever.types index 4ec24ed772abb..fb6b3904f3a5a 100644 --- a/tests/baselines/reference/indexingTypesWithNever.types +++ b/tests/baselines/reference/indexingTypesWithNever.types @@ -117,8 +117,8 @@ declare const key: never >key : never const result6 = obj[key] ->result6 : any ->obj[key] : any +>result6 : never +>obj[key] : never >obj : { a: string; b: number; } >key : never