mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-06 20:14:01 -06:00
Merge pull request #21947 from Microsoft/fixKeyofWildcard
Fix issue with 'keyof T' and conditional types
This commit is contained in:
commit
0f697c376b
@ -7949,6 +7949,7 @@ namespace ts {
|
||||
function getIndexType(type: Type): Type {
|
||||
return maybeTypeOfKind(type, TypeFlags.InstantiableNonPrimitive) ? getIndexTypeForGenericType(<InstantiableType | UnionOrIntersectionType>type) :
|
||||
getObjectFlags(type) & ObjectFlags.Mapped ? getConstraintTypeFromMappedType(<MappedType>type) :
|
||||
type === wildcardType ? wildcardType :
|
||||
type.flags & TypeFlags.Any || getIndexInfoOfType(type, IndexKind.String) ? stringType :
|
||||
getLiteralTypeFromPropertyNames(type);
|
||||
}
|
||||
|
||||
@ -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<T extends string, U extends string> = (
|
||||
& { [P in T]: P; }
|
||||
& { [P in U]: never; }
|
||||
& { [x: string]: never; }
|
||||
)[T];
|
||||
type NewDiff<T, U> = T extends U ? never : T;
|
||||
interface A {
|
||||
a: 'a';
|
||||
}
|
||||
interface B1 extends A {
|
||||
b: 'b';
|
||||
c: OldDiff<keyof this, keyof A>;
|
||||
}
|
||||
interface B2 extends A {
|
||||
b: 'b';
|
||||
c: NewDiff<keyof this, keyof A>;
|
||||
}
|
||||
type c1 = B1['c']; // 'c' | 'b'
|
||||
type c2 = B2['c']; // 'c' | 'b'
|
||||
|
||||
// Repro from #21929
|
||||
|
||||
type NonFooKeys1<T extends object> = OldDiff<keyof T, 'foo'>;
|
||||
type NonFooKeys2<T extends object> = Exclude<keyof T, 'foo'>;
|
||||
|
||||
type Test1 = NonFooKeys1<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz"
|
||||
type Test2 = NonFooKeys2<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz"
|
||||
|
||||
@ -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<T extends string, U extends string> = (
|
||||
& { [P in T]: P; }
|
||||
& { [P in U]: never; }
|
||||
& { [x: string]: never; }
|
||||
)[T];
|
||||
type NewDiff<T, U> = T extends U ? never : T;
|
||||
interface A {
|
||||
a: 'a';
|
||||
}
|
||||
interface B1 extends A {
|
||||
b: 'b';
|
||||
c: OldDiff<keyof this, keyof A>;
|
||||
}
|
||||
interface B2 extends A {
|
||||
b: 'b';
|
||||
c: NewDiff<keyof this, keyof A>;
|
||||
}
|
||||
type c1 = B1['c']; // 'c' | 'b'
|
||||
type c2 = B2['c']; // 'c' | 'b'
|
||||
|
||||
// Repro from #21929
|
||||
|
||||
type NonFooKeys1<T extends object> = OldDiff<keyof T, 'foo'>;
|
||||
type NonFooKeys2<T extends object> = Exclude<keyof T, 'foo'>;
|
||||
|
||||
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> = T extends string ? boolean : number;
|
||||
declare const f44: <U>(value: T94<U>) => T95<U>;
|
||||
declare const f45: <U>(value: T95<U>) => T94<U>;
|
||||
declare function f50(): void;
|
||||
declare type OldDiff<T extends string, U extends string> = ({
|
||||
[P in T]: P;
|
||||
} & {
|
||||
[P in U]: never;
|
||||
} & {
|
||||
[x: string]: never;
|
||||
})[T];
|
||||
declare type NewDiff<T, U> = T extends U ? never : T;
|
||||
interface A {
|
||||
a: 'a';
|
||||
}
|
||||
interface B1 extends A {
|
||||
b: 'b';
|
||||
c: OldDiff<keyof this, keyof A>;
|
||||
}
|
||||
interface B2 extends A {
|
||||
b: 'b';
|
||||
c: NewDiff<keyof this, keyof A>;
|
||||
}
|
||||
declare type c1 = B1['c'];
|
||||
declare type c2 = B2['c'];
|
||||
declare type NonFooKeys1<T extends object> = OldDiff<keyof T, 'foo'>;
|
||||
declare type NonFooKeys2<T extends object> = Exclude<keyof T, 'foo'>;
|
||||
declare type Test1 = NonFooKeys1<{
|
||||
foo: 1;
|
||||
bar: 2;
|
||||
baz: 3;
|
||||
}>;
|
||||
declare type Test2 = NonFooKeys2<{
|
||||
foo: 1;
|
||||
bar: 2;
|
||||
baz: 3;
|
||||
}>;
|
||||
|
||||
@ -1121,3 +1121,99 @@ function f50() {
|
||||
>b : Symbol(b, Decl(conditionalTypes1.ts, 284, 29))
|
||||
}
|
||||
|
||||
// Repro from #21862
|
||||
|
||||
type OldDiff<T extends string, U extends string> = (
|
||||
>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, U> = 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<keyof this, keyof A>;
|
||||
>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<keyof this, keyof A>;
|
||||
>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<T extends object> = OldDiff<keyof T, 'foo'>;
|
||||
>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<T extends object> = Exclude<keyof T, 'foo'>;
|
||||
>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))
|
||||
|
||||
|
||||
@ -1274,3 +1274,99 @@ function f50() {
|
||||
>b : never
|
||||
}
|
||||
|
||||
// Repro from #21862
|
||||
|
||||
type OldDiff<T extends string, U extends string> = (
|
||||
>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, U> = T extends U ? never : T;
|
||||
>NewDiff : NewDiff<T, U>
|
||||
>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<keyof this, keyof A>;
|
||||
>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<keyof this, keyof A>;
|
||||
>c : NewDiff<keyof this, "a">
|
||||
>NewDiff : NewDiff<T, U>
|
||||
>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<T extends object> = OldDiff<keyof T, 'foo'>;
|
||||
>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<T extends object> = Exclude<keyof T, 'foo'>;
|
||||
>NonFooKeys2 : Exclude<keyof T, "foo">
|
||||
>T : T
|
||||
>Exclude : Exclude<T, U>
|
||||
>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<keyof T, "foo">
|
||||
>foo : 1
|
||||
>bar : 2
|
||||
>baz : 3
|
||||
|
||||
|
||||
@ -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<T extends string, U extends string> = (
|
||||
& { [P in T]: P; }
|
||||
& { [P in U]: never; }
|
||||
& { [x: string]: never; }
|
||||
)[T];
|
||||
type NewDiff<T, U> = T extends U ? never : T;
|
||||
interface A {
|
||||
a: 'a';
|
||||
}
|
||||
interface B1 extends A {
|
||||
b: 'b';
|
||||
c: OldDiff<keyof this, keyof A>;
|
||||
}
|
||||
interface B2 extends A {
|
||||
b: 'b';
|
||||
c: NewDiff<keyof this, keyof A>;
|
||||
}
|
||||
type c1 = B1['c']; // 'c' | 'b'
|
||||
type c2 = B2['c']; // 'c' | 'b'
|
||||
|
||||
// Repro from #21929
|
||||
|
||||
type NonFooKeys1<T extends object> = OldDiff<keyof T, 'foo'>;
|
||||
type NonFooKeys2<T extends object> = Exclude<keyof T, 'foo'>;
|
||||
|
||||
type Test1 = NonFooKeys1<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz"
|
||||
type Test2 = NonFooKeys2<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user