diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index df69b4d8efe..2df80926c14 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7949,6 +7949,7 @@ namespace ts { function getIndexType(type: Type): Type { return maybeTypeOfKind(type, TypeFlags.InstantiableNonPrimitive) ? getIndexTypeForGenericType(type) : getObjectFlags(type) & ObjectFlags.Mapped ? getConstraintTypeFromMappedType(type) : + type === wildcardType ? wildcardType : type.flags & TypeFlags.Any || getIndexInfoOfType(type, IndexKind.String) ? stringType : getLiteralTypeFromPropertyNames(type); } diff --git a/tests/baselines/reference/conditionalTypes1.errors.txt b/tests/baselines/reference/conditionalTypes1.errors.txt index 869e740ad1a..72d88b60d64 100644 --- a/tests/baselines/reference/conditionalTypes1.errors.txt +++ b/tests/baselines/reference/conditionalTypes1.errors.txt @@ -447,4 +447,34 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(275,43): error TS type A = Omit<{ a: void; b: never; }>; // 'a' type B = Omit2<{ a: void; b: never; }>; // 'a' } + + // Repro from #21862 + + type OldDiff = ( + & { [P in T]: P; } + & { [P in U]: never; } + & { [x: string]: never; } + )[T]; + type NewDiff = T extends U ? never : T; + interface A { + a: 'a'; + } + interface B1 extends A { + b: 'b'; + c: OldDiff; + } + interface B2 extends A { + b: 'b'; + c: NewDiff; + } + type c1 = B1['c']; // 'c' | 'b' + type c2 = B2['c']; // 'c' | 'b' + + // Repro from #21929 + + type NonFooKeys1 = OldDiff; + type NonFooKeys2 = Exclude; + + type Test1 = NonFooKeys1<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz" + type Test2 = NonFooKeys2<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz" \ No newline at end of file diff --git a/tests/baselines/reference/conditionalTypes1.js b/tests/baselines/reference/conditionalTypes1.js index 9020774d7fe..c7ad450f712 100644 --- a/tests/baselines/reference/conditionalTypes1.js +++ b/tests/baselines/reference/conditionalTypes1.js @@ -285,6 +285,36 @@ function f50() { type A = Omit<{ a: void; b: never; }>; // 'a' type B = Omit2<{ a: void; b: never; }>; // 'a' } + +// Repro from #21862 + +type OldDiff = ( + & { [P in T]: P; } + & { [P in U]: never; } + & { [x: string]: never; } +)[T]; +type NewDiff = T extends U ? never : T; +interface A { + a: 'a'; +} +interface B1 extends A { + b: 'b'; + c: OldDiff; +} +interface B2 extends A { + b: 'b'; + c: NewDiff; +} +type c1 = B1['c']; // 'c' | 'b' +type c2 = B2['c']; // 'c' | 'b' + +// Repro from #21929 + +type NonFooKeys1 = OldDiff; +type NonFooKeys2 = Exclude; + +type Test1 = NonFooKeys1<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz" +type Test2 = NonFooKeys2<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz" //// [conditionalTypes1.js] @@ -561,3 +591,36 @@ declare type T95 = T extends string ? boolean : number; declare const f44: (value: T94) => T95; declare const f45: (value: T95) => T94; declare function f50(): void; +declare type OldDiff = ({ + [P in T]: P; +} & { + [P in U]: never; +} & { + [x: string]: never; +})[T]; +declare type NewDiff = T extends U ? never : T; +interface A { + a: 'a'; +} +interface B1 extends A { + b: 'b'; + c: OldDiff; +} +interface B2 extends A { + b: 'b'; + c: NewDiff; +} +declare type c1 = B1['c']; +declare type c2 = B2['c']; +declare type NonFooKeys1 = OldDiff; +declare type NonFooKeys2 = Exclude; +declare type Test1 = NonFooKeys1<{ + foo: 1; + bar: 2; + baz: 3; +}>; +declare type Test2 = NonFooKeys2<{ + foo: 1; + bar: 2; + baz: 3; +}>; diff --git a/tests/baselines/reference/conditionalTypes1.symbols b/tests/baselines/reference/conditionalTypes1.symbols index 6c05ee1eeee..8802f25b1a8 100644 --- a/tests/baselines/reference/conditionalTypes1.symbols +++ b/tests/baselines/reference/conditionalTypes1.symbols @@ -1121,3 +1121,99 @@ function f50() { >b : Symbol(b, Decl(conditionalTypes1.ts, 284, 29)) } +// Repro from #21862 + +type OldDiff = ( +>OldDiff : Symbol(OldDiff, Decl(conditionalTypes1.ts, 285, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 289, 13)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 289, 30)) + + & { [P in T]: P; } +>P : Symbol(P, Decl(conditionalTypes1.ts, 290, 9)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 289, 13)) +>P : Symbol(P, Decl(conditionalTypes1.ts, 290, 9)) + + & { [P in U]: never; } +>P : Symbol(P, Decl(conditionalTypes1.ts, 291, 9)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 289, 30)) + + & { [x: string]: never; } +>x : Symbol(x, Decl(conditionalTypes1.ts, 292, 9)) + +)[T]; +>T : Symbol(T, Decl(conditionalTypes1.ts, 289, 13)) + +type NewDiff = T extends U ? never : T; +>NewDiff : Symbol(NewDiff, Decl(conditionalTypes1.ts, 293, 5)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 294, 13)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 294, 15)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 294, 13)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 294, 15)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 294, 13)) + +interface A { +>A : Symbol(A, Decl(conditionalTypes1.ts, 294, 45)) + + a: 'a'; +>a : Symbol(A.a, Decl(conditionalTypes1.ts, 295, 13)) +} +interface B1 extends A { +>B1 : Symbol(B1, Decl(conditionalTypes1.ts, 297, 1)) +>A : Symbol(A, Decl(conditionalTypes1.ts, 294, 45)) + + b: 'b'; +>b : Symbol(B1.b, Decl(conditionalTypes1.ts, 298, 24)) + + c: OldDiff; +>c : Symbol(B1.c, Decl(conditionalTypes1.ts, 299, 11)) +>OldDiff : Symbol(OldDiff, Decl(conditionalTypes1.ts, 285, 1)) +>A : Symbol(A, Decl(conditionalTypes1.ts, 294, 45)) +} +interface B2 extends A { +>B2 : Symbol(B2, Decl(conditionalTypes1.ts, 301, 1)) +>A : Symbol(A, Decl(conditionalTypes1.ts, 294, 45)) + + b: 'b'; +>b : Symbol(B2.b, Decl(conditionalTypes1.ts, 302, 24)) + + c: NewDiff; +>c : Symbol(B2.c, Decl(conditionalTypes1.ts, 303, 11)) +>NewDiff : Symbol(NewDiff, Decl(conditionalTypes1.ts, 293, 5)) +>A : Symbol(A, Decl(conditionalTypes1.ts, 294, 45)) +} +type c1 = B1['c']; // 'c' | 'b' +>c1 : Symbol(c1, Decl(conditionalTypes1.ts, 305, 1)) +>B1 : Symbol(B1, Decl(conditionalTypes1.ts, 297, 1)) + +type c2 = B2['c']; // 'c' | 'b' +>c2 : Symbol(c2, Decl(conditionalTypes1.ts, 306, 18)) +>B2 : Symbol(B2, Decl(conditionalTypes1.ts, 301, 1)) + +// Repro from #21929 + +type NonFooKeys1 = OldDiff; +>NonFooKeys1 : Symbol(NonFooKeys1, Decl(conditionalTypes1.ts, 307, 18)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 311, 17)) +>OldDiff : Symbol(OldDiff, Decl(conditionalTypes1.ts, 285, 1)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 311, 17)) + +type NonFooKeys2 = Exclude; +>NonFooKeys2 : Symbol(NonFooKeys2, Decl(conditionalTypes1.ts, 311, 61)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 312, 17)) +>Exclude : Symbol(Exclude, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 312, 17)) + +type Test1 = NonFooKeys1<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz" +>Test1 : Symbol(Test1, Decl(conditionalTypes1.ts, 312, 61)) +>NonFooKeys1 : Symbol(NonFooKeys1, Decl(conditionalTypes1.ts, 307, 18)) +>foo : Symbol(foo, Decl(conditionalTypes1.ts, 314, 26)) +>bar : Symbol(bar, Decl(conditionalTypes1.ts, 314, 33)) +>baz : Symbol(baz, Decl(conditionalTypes1.ts, 314, 41)) + +type Test2 = NonFooKeys2<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz" +>Test2 : Symbol(Test2, Decl(conditionalTypes1.ts, 314, 51)) +>NonFooKeys2 : Symbol(NonFooKeys2, Decl(conditionalTypes1.ts, 311, 61)) +>foo : Symbol(foo, Decl(conditionalTypes1.ts, 315, 26)) +>bar : Symbol(bar, Decl(conditionalTypes1.ts, 315, 33)) +>baz : Symbol(baz, Decl(conditionalTypes1.ts, 315, 41)) + diff --git a/tests/baselines/reference/conditionalTypes1.types b/tests/baselines/reference/conditionalTypes1.types index b544acdf3e2..1eebf8ba833 100644 --- a/tests/baselines/reference/conditionalTypes1.types +++ b/tests/baselines/reference/conditionalTypes1.types @@ -1274,3 +1274,99 @@ function f50() { >b : never } +// Repro from #21862 + +type OldDiff = ( +>OldDiff : ({ [P in T]: P; } & { [P in U]: never; } & { [x: string]: never; })[T] +>T : T +>U : U + + & { [P in T]: P; } +>P : P +>T : T +>P : P + + & { [P in U]: never; } +>P : P +>U : U + + & { [x: string]: never; } +>x : string + +)[T]; +>T : T + +type NewDiff = T extends U ? never : T; +>NewDiff : NewDiff +>T : T +>U : U +>T : T +>U : U +>T : T + +interface A { +>A : A + + a: 'a'; +>a : "a" +} +interface B1 extends A { +>B1 : B1 +>A : A + + b: 'b'; +>b : "b" + + c: OldDiff; +>c : ({ [P in keyof this]: P; } & { a: never; } & { [x: string]: never; })[keyof this] +>OldDiff : ({ [P in T]: P; } & { [P in U]: never; } & { [x: string]: never; })[T] +>A : A +} +interface B2 extends A { +>B2 : B2 +>A : A + + b: 'b'; +>b : "b" + + c: NewDiff; +>c : NewDiff +>NewDiff : NewDiff +>A : A +} +type c1 = B1['c']; // 'c' | 'b' +>c1 : "b" | "c" +>B1 : B1 + +type c2 = B2['c']; // 'c' | 'b' +>c2 : "b" | "c" +>B2 : B2 + +// Repro from #21929 + +type NonFooKeys1 = OldDiff; +>NonFooKeys1 : ({ [P in keyof T]: P; } & { foo: never; } & { [x: string]: never; })[keyof T] +>T : T +>OldDiff : ({ [P in T]: P; } & { [P in U]: never; } & { [x: string]: never; })[T] +>T : T + +type NonFooKeys2 = Exclude; +>NonFooKeys2 : Exclude +>T : T +>Exclude : Exclude +>T : T + +type Test1 = NonFooKeys1<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz" +>Test1 : "bar" | "baz" +>NonFooKeys1 : ({ [P in keyof T]: P; } & { foo: never; } & { [x: string]: never; })[keyof T] +>foo : 1 +>bar : 2 +>baz : 3 + +type Test2 = NonFooKeys2<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz" +>Test2 : "bar" | "baz" +>NonFooKeys2 : Exclude +>foo : 1 +>bar : 2 +>baz : 3 + diff --git a/tests/cases/conformance/types/conditional/conditionalTypes1.ts b/tests/cases/conformance/types/conditional/conditionalTypes1.ts index 94a802a0ffc..9449cc6d766 100644 --- a/tests/cases/conformance/types/conditional/conditionalTypes1.ts +++ b/tests/cases/conformance/types/conditional/conditionalTypes1.ts @@ -287,3 +287,33 @@ function f50() { type A = Omit<{ a: void; b: never; }>; // 'a' type B = Omit2<{ a: void; b: never; }>; // 'a' } + +// Repro from #21862 + +type OldDiff = ( + & { [P in T]: P; } + & { [P in U]: never; } + & { [x: string]: never; } +)[T]; +type NewDiff = T extends U ? never : T; +interface A { + a: 'a'; +} +interface B1 extends A { + b: 'b'; + c: OldDiff; +} +interface B2 extends A { + b: 'b'; + c: NewDiff; +} +type c1 = B1['c']; // 'c' | 'b' +type c2 = B2['c']; // 'c' | 'b' + +// Repro from #21929 + +type NonFooKeys1 = OldDiff; +type NonFooKeys2 = Exclude; + +type Test1 = NonFooKeys1<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz" +type Test2 = NonFooKeys2<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz"