mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-10 06:41:59 -06:00
Merge pull request #27490 from Microsoft/indexedAccessConstraint
Limit unsound indexed access type relations
This commit is contained in:
commit
9851d6f457
@ -11897,8 +11897,9 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else if (target.flags & TypeFlags.IndexedAccess) {
|
||||
// A type S is related to a type T[K] if S is related to C, where C is the base constraint of T[K]
|
||||
if (relation !== identityRelation) {
|
||||
// A type S is related to a type T[K], where T and K aren't both type variables, if S is related to C,
|
||||
// where C is the base constraint of T[K]
|
||||
if (relation !== identityRelation && !(isGenericObjectType((<IndexedAccessType>target).objectType) && isGenericIndexType((<IndexedAccessType>target).indexType))) {
|
||||
const constraint = getBaseConstraintOfType(target);
|
||||
if (constraint && constraint !== target) {
|
||||
if (result = isRelatedTo(source, constraint, reportErrors)) {
|
||||
|
||||
@ -1,19 +1,10 @@
|
||||
error TS2321: Excessive stack depth comparing types 'Extract<T[Exclude<keyof T, number>], Record<"val", string>>["val"]' and 'Extract<T[Exclude<keyof T, Exclude<keyof T, number>>], Record<"val", string>>["val"]'.
|
||||
error TS2321: Excessive stack depth comparing types 'Extract<T[Exclude<keyof T, string>], Record<"val", string>>["val"]' and 'Extract<T[Exclude<keyof T, Exclude<keyof T, string>>], Record<"val", string>>["val"]'.
|
||||
error TS2321: Excessive stack depth comparing types 'Extract<T[Exclude<keyof T, symbol>], Record<"val", string>>["val"]' and 'Extract<T[Exclude<keyof T, Exclude<keyof T, symbol>>], Record<"val", string>>["val"]'.
|
||||
tests/cases/compiler/infiniteConstraints.ts(4,37): error TS2536: Type '"val"' cannot be used to index type 'B[Exclude<keyof B, K>]'.
|
||||
tests/cases/compiler/infiniteConstraints.ts(27,37): error TS2322: Type 'Record<"val", "test">' is not assignable to type 'never'.
|
||||
tests/cases/compiler/infiniteConstraints.ts(27,58): error TS2322: Type 'Record<"val", "test2">' is not assignable to type 'never'.
|
||||
tests/cases/compiler/infiniteConstraints.ts(29,45): error TS2322: Type 'Record<"val", "test">' is not assignable to type 'never'.
|
||||
tests/cases/compiler/infiniteConstraints.ts(31,43): error TS2322: Type 'Record<"val", "dup">' is not assignable to type 'never'.
|
||||
tests/cases/compiler/infiniteConstraints.ts(31,63): error TS2322: Type 'Record<"val", "dup">' is not assignable to type 'never'.
|
||||
tests/cases/compiler/infiniteConstraints.ts(36,71): error TS2536: Type '"foo"' cannot be used to index type 'T[keyof T]'.
|
||||
|
||||
|
||||
!!! error TS2321: Excessive stack depth comparing types 'Extract<T[Exclude<keyof T, number>], Record<"val", string>>["val"]' and 'Extract<T[Exclude<keyof T, Exclude<keyof T, number>>], Record<"val", string>>["val"]'.
|
||||
!!! error TS2321: Excessive stack depth comparing types 'Extract<T[Exclude<keyof T, string>], Record<"val", string>>["val"]' and 'Extract<T[Exclude<keyof T, Exclude<keyof T, string>>], Record<"val", string>>["val"]'.
|
||||
!!! error TS2321: Excessive stack depth comparing types 'Extract<T[Exclude<keyof T, symbol>], Record<"val", string>>["val"]' and 'Extract<T[Exclude<keyof T, Exclude<keyof T, symbol>>], Record<"val", string>>["val"]'.
|
||||
==== tests/cases/compiler/infiniteConstraints.ts (7 errors) ====
|
||||
==== tests/cases/compiler/infiniteConstraints.ts (4 errors) ====
|
||||
// Both of the following types trigger the recursion limiter in getImmediateBaseConstraint
|
||||
|
||||
type T1<B extends { [K in keyof B]: Extract<B[Exclude<keyof B, K>], { val: string }>["val"] }> = B;
|
||||
@ -43,17 +34,8 @@ tests/cases/compiler/infiniteConstraints.ts(36,71): error TS2536: Type '"foo"' c
|
||||
>(vals: T): void;
|
||||
|
||||
const noError = ensureNoDuplicates({main: value("test"), alternate: value("test2")});
|
||||
~~~~
|
||||
!!! error TS2322: Type 'Record<"val", "test">' is not assignable to type 'never'.
|
||||
!!! related TS6500 tests/cases/compiler/infiniteConstraints.ts:27:37: The expected type comes from property 'main' which is declared here on type '{ main: never; alternate: never; }'
|
||||
~~~~~~~~~
|
||||
!!! error TS2322: Type 'Record<"val", "test2">' is not assignable to type 'never'.
|
||||
!!! related TS6500 tests/cases/compiler/infiniteConstraints.ts:27:58: The expected type comes from property 'alternate' which is declared here on type '{ main: never; alternate: never; }'
|
||||
|
||||
const shouldBeNoError = ensureNoDuplicates({main: value("test")});
|
||||
~~~~
|
||||
!!! error TS2322: Type 'Record<"val", "test">' is not assignable to type 'never'.
|
||||
!!! related TS6500 tests/cases/compiler/infiniteConstraints.ts:29:45: The expected type comes from property 'main' which is declared here on type '{ main: never; }'
|
||||
|
||||
const shouldBeError = ensureNoDuplicates({main: value("dup"), alternate: value("dup")});
|
||||
~~~~
|
||||
|
||||
@ -39,7 +39,7 @@ declare function value<V extends string>(val: V): Value<V>;
|
||||
>val : V
|
||||
|
||||
declare function ensureNoDuplicates<
|
||||
>ensureNoDuplicates : <T extends { [K in keyof T]: never; }>(vals: T) => void
|
||||
>ensureNoDuplicates : <T extends { [K in keyof T]: Extract<T[K], Record<"val", string>>["val"] extends Extract<T[Exclude<keyof T, K>], Record<"val", string>>["val"] ? never : any; }>(vals: T) => void
|
||||
|
||||
T extends {
|
||||
[K in keyof T]: Extract<T[K], Value>["val"] extends Extract<T[Exclude<keyof T, K>], Value>["val"]
|
||||
@ -50,9 +50,9 @@ declare function ensureNoDuplicates<
|
||||
>vals : T
|
||||
|
||||
const noError = ensureNoDuplicates({main: value("test"), alternate: value("test2")});
|
||||
>noError : any
|
||||
>ensureNoDuplicates({main: value("test"), alternate: value("test2")}) : any
|
||||
>ensureNoDuplicates : <T extends { [K in keyof T]: never; }>(vals: T) => void
|
||||
>noError : void
|
||||
>ensureNoDuplicates({main: value("test"), alternate: value("test2")}) : void
|
||||
>ensureNoDuplicates : <T extends { [K in keyof T]: Extract<T[K], Record<"val", string>>["val"] extends Extract<T[Exclude<keyof T, K>], Record<"val", string>>["val"] ? never : any; }>(vals: T) => void
|
||||
>{main: value("test"), alternate: value("test2")} : { main: Record<"val", "test">; alternate: Record<"val", "test2">; }
|
||||
>main : Record<"val", "test">
|
||||
>value("test") : Record<"val", "test">
|
||||
@ -64,9 +64,9 @@ const noError = ensureNoDuplicates({main: value("test"), alternate: value("test2
|
||||
>"test2" : "test2"
|
||||
|
||||
const shouldBeNoError = ensureNoDuplicates({main: value("test")});
|
||||
>shouldBeNoError : any
|
||||
>ensureNoDuplicates({main: value("test")}) : any
|
||||
>ensureNoDuplicates : <T extends { [K in keyof T]: never; }>(vals: T) => void
|
||||
>shouldBeNoError : void
|
||||
>ensureNoDuplicates({main: value("test")}) : void
|
||||
>ensureNoDuplicates : <T extends { [K in keyof T]: Extract<T[K], Record<"val", string>>["val"] extends Extract<T[Exclude<keyof T, K>], Record<"val", string>>["val"] ? never : any; }>(vals: T) => void
|
||||
>{main: value("test")} : { main: Record<"val", "test">; }
|
||||
>main : Record<"val", "test">
|
||||
>value("test") : Record<"val", "test">
|
||||
@ -76,7 +76,7 @@ const shouldBeNoError = ensureNoDuplicates({main: value("test")});
|
||||
const shouldBeError = ensureNoDuplicates({main: value("dup"), alternate: value("dup")});
|
||||
>shouldBeError : any
|
||||
>ensureNoDuplicates({main: value("dup"), alternate: value("dup")}) : any
|
||||
>ensureNoDuplicates : <T extends { [K in keyof T]: never; }>(vals: T) => void
|
||||
>ensureNoDuplicates : <T extends { [K in keyof T]: Extract<T[K], Record<"val", string>>["val"] extends Extract<T[Exclude<keyof T, K>], Record<"val", string>>["val"] ? never : any; }>(vals: T) => void
|
||||
>{main: value("dup"), alternate: value("dup")} : { main: Record<"val", "dup">; alternate: Record<"val", "dup">; }
|
||||
>main : Record<"val", "dup">
|
||||
>value("dup") : Record<"val", "dup">
|
||||
|
||||
@ -300,23 +300,16 @@ type S2 = {
|
||||
b: string;
|
||||
};
|
||||
|
||||
function f90<T extends S2, K extends keyof S2>(x1: S2[keyof S2], x2: T[keyof S2], x3: S2[K], x4: T[K]) {
|
||||
function f90<T extends S2, K extends keyof S2>(x1: S2[keyof S2], x2: T[keyof S2], x3: S2[K]) {
|
||||
x1 = x2;
|
||||
x1 = x3;
|
||||
x1 = x4;
|
||||
x2 = x1;
|
||||
x2 = x3;
|
||||
x2 = x4;
|
||||
x3 = x1;
|
||||
x3 = x2;
|
||||
x3 = x4;
|
||||
x4 = x1;
|
||||
x4 = x2;
|
||||
x4 = x3;
|
||||
x1.length;
|
||||
x2.length;
|
||||
x3.length;
|
||||
x4.length;
|
||||
}
|
||||
|
||||
function f91<T, K extends keyof T>(x: T, y: T[keyof T], z: T[K]) {
|
||||
@ -886,23 +879,16 @@ var C1 = /** @class */ (function () {
|
||||
};
|
||||
return C1;
|
||||
}());
|
||||
function f90(x1, x2, x3, x4) {
|
||||
function f90(x1, x2, x3) {
|
||||
x1 = x2;
|
||||
x1 = x3;
|
||||
x1 = x4;
|
||||
x2 = x1;
|
||||
x2 = x3;
|
||||
x2 = x4;
|
||||
x3 = x1;
|
||||
x3 = x2;
|
||||
x3 = x4;
|
||||
x4 = x1;
|
||||
x4 = x2;
|
||||
x4 = x3;
|
||||
x1.length;
|
||||
x2.length;
|
||||
x3.length;
|
||||
x4.length;
|
||||
}
|
||||
function f91(x, y, z) {
|
||||
var a;
|
||||
@ -1240,7 +1226,7 @@ declare type S2 = {
|
||||
a: string;
|
||||
b: string;
|
||||
};
|
||||
declare function f90<T extends S2, K extends keyof S2>(x1: S2[keyof S2], x2: T[keyof S2], x3: S2[K], x4: T[K]): void;
|
||||
declare function f90<T extends S2, K extends keyof S2>(x1: S2[keyof S2], x2: T[keyof S2], x3: S2[K]): void;
|
||||
declare function f91<T, K extends keyof T>(x: T, y: T[keyof T], z: T[K]): void;
|
||||
declare function f92<T, K extends keyof T>(x: T, y: T[keyof T], z: T[K]): void;
|
||||
declare class Base {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1207,12 +1207,11 @@ type S2 = {
|
||||
|
||||
};
|
||||
|
||||
function f90<T extends S2, K extends keyof S2>(x1: S2[keyof S2], x2: T[keyof S2], x3: S2[K], x4: T[K]) {
|
||||
>f90 : <T extends S2, K extends "a" | "b">(x1: string, x2: T["a" | "b"], x3: S2[K], x4: T[K]) => void
|
||||
function f90<T extends S2, K extends keyof S2>(x1: S2[keyof S2], x2: T[keyof S2], x3: S2[K]) {
|
||||
>f90 : <T extends S2, K extends "a" | "b">(x1: string, x2: T["a" | "b"], x3: S2[K]) => void
|
||||
>x1 : string
|
||||
>x2 : T["a" | "b"]
|
||||
>x3 : S2[K]
|
||||
>x4 : T[K]
|
||||
|
||||
x1 = x2;
|
||||
>x1 = x2 : T["a" | "b"]
|
||||
@ -1224,11 +1223,6 @@ function f90<T extends S2, K extends keyof S2>(x1: S2[keyof S2], x2: T[keyof S2]
|
||||
>x1 : string
|
||||
>x3 : S2[K]
|
||||
|
||||
x1 = x4;
|
||||
>x1 = x4 : T[K]
|
||||
>x1 : string
|
||||
>x4 : T[K]
|
||||
|
||||
x2 = x1;
|
||||
>x2 = x1 : string
|
||||
>x2 : T["a" | "b"]
|
||||
@ -1239,11 +1233,6 @@ function f90<T extends S2, K extends keyof S2>(x1: S2[keyof S2], x2: T[keyof S2]
|
||||
>x2 : T["a" | "b"]
|
||||
>x3 : S2[K]
|
||||
|
||||
x2 = x4;
|
||||
>x2 = x4 : T[K]
|
||||
>x2 : T["a" | "b"]
|
||||
>x4 : T[K]
|
||||
|
||||
x3 = x1;
|
||||
>x3 = x1 : string
|
||||
>x3 : S2[K]
|
||||
@ -1254,26 +1243,6 @@ function f90<T extends S2, K extends keyof S2>(x1: S2[keyof S2], x2: T[keyof S2]
|
||||
>x3 : S2[K]
|
||||
>x2 : T["a" | "b"]
|
||||
|
||||
x3 = x4;
|
||||
>x3 = x4 : T[K]
|
||||
>x3 : S2[K]
|
||||
>x4 : T[K]
|
||||
|
||||
x4 = x1;
|
||||
>x4 = x1 : string
|
||||
>x4 : T[K]
|
||||
>x1 : string
|
||||
|
||||
x4 = x2;
|
||||
>x4 = x2 : T["a" | "b"]
|
||||
>x4 : T[K]
|
||||
>x2 : T["a" | "b"]
|
||||
|
||||
x4 = x3;
|
||||
>x4 = x3 : S2[K]
|
||||
>x4 : T[K]
|
||||
>x3 : S2[K]
|
||||
|
||||
x1.length;
|
||||
>x1.length : number
|
||||
>x1 : string
|
||||
@ -1287,11 +1256,6 @@ function f90<T extends S2, K extends keyof S2>(x1: S2[keyof S2], x2: T[keyof S2]
|
||||
x3.length;
|
||||
>x3.length : number
|
||||
>x3 : S2[K]
|
||||
>length : number
|
||||
|
||||
x4.length;
|
||||
>x4.length : number
|
||||
>x4 : T[K]
|
||||
>length : number
|
||||
}
|
||||
|
||||
|
||||
@ -63,9 +63,12 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(117,5): error
|
||||
Type 'T' is not assignable to type 'U'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(122,5): error TS2322: Type '42' is not assignable to type 'keyof T'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(123,5): error TS2322: Type '"hello"' is not assignable to type 'keyof T'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(140,5): error TS2322: Type '42' is not assignable to type 'T[K]'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(141,5): error TS2322: Type '"hello"' is not assignable to type 'T[K]'.
|
||||
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(142,5): error TS2322: Type 'number[]' is not assignable to type 'T[K]'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts (38 errors) ====
|
||||
==== tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts (41 errors) ====
|
||||
class Shape {
|
||||
name: string;
|
||||
width: number;
|
||||
@ -293,4 +296,29 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(123,5): error
|
||||
~
|
||||
!!! error TS2322: Type '"hello"' is not assignable to type 'keyof T'.
|
||||
}
|
||||
|
||||
// Repro from #27470
|
||||
|
||||
type UndefinedKeys<T extends Record<string, any>> = {
|
||||
[K in keyof T]: undefined extends T[K] ? K : never
|
||||
};
|
||||
|
||||
type MyType = {a: string, b: string | undefined}
|
||||
|
||||
type Result1 = UndefinedKeys<MyType>;
|
||||
|
||||
const a1: Result1['a'] = 'a'; // Error
|
||||
const b1: Result1['b'] = 'b';
|
||||
|
||||
function test1<T extends Record<string, any>, K extends keyof T>(t: T, k: K) {
|
||||
t[k] = 42; // Error
|
||||
~~~~
|
||||
!!! error TS2322: Type '42' is not assignable to type 'T[K]'.
|
||||
t[k] = "hello"; // Error
|
||||
~~~~
|
||||
!!! error TS2322: Type '"hello"' is not assignable to type 'T[K]'.
|
||||
t[k] = [10, 20]; // Error
|
||||
~~~~
|
||||
!!! error TS2322: Type 'number[]' is not assignable to type 'T[K]'.
|
||||
}
|
||||
|
||||
@ -123,6 +123,25 @@ function f4<T extends { [K in keyof T]: string }>(k: keyof T) {
|
||||
k = 42; // error
|
||||
k = "hello"; // error
|
||||
}
|
||||
|
||||
// Repro from #27470
|
||||
|
||||
type UndefinedKeys<T extends Record<string, any>> = {
|
||||
[K in keyof T]: undefined extends T[K] ? K : never
|
||||
};
|
||||
|
||||
type MyType = {a: string, b: string | undefined}
|
||||
|
||||
type Result1 = UndefinedKeys<MyType>;
|
||||
|
||||
const a1: Result1['a'] = 'a'; // Error
|
||||
const b1: Result1['b'] = 'b';
|
||||
|
||||
function test1<T extends Record<string, any>, K extends keyof T>(t: T, k: K) {
|
||||
t[k] = 42; // Error
|
||||
t[k] = "hello"; // Error
|
||||
t[k] = [10, 20]; // Error
|
||||
}
|
||||
|
||||
|
||||
//// [keyofAndIndexedAccessErrors.js]
|
||||
@ -189,3 +208,10 @@ function f4(k) {
|
||||
k = 42; // error
|
||||
k = "hello"; // error
|
||||
}
|
||||
var a1 = 'a'; // Error
|
||||
var b1 = 'b';
|
||||
function test1(t, k) {
|
||||
t[k] = 42; // Error
|
||||
t[k] = "hello"; // Error
|
||||
t[k] = [10, 20]; // Error
|
||||
}
|
||||
|
||||
@ -428,3 +428,61 @@ function f4<T extends { [K in keyof T]: string }>(k: keyof T) {
|
||||
>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 120, 50))
|
||||
}
|
||||
|
||||
// Repro from #27470
|
||||
|
||||
type UndefinedKeys<T extends Record<string, any>> = {
|
||||
>UndefinedKeys : Symbol(UndefinedKeys, Decl(keyofAndIndexedAccessErrors.ts, 123, 1))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 127, 19))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
[K in keyof T]: undefined extends T[K] ? K : never
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 128, 3))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 127, 19))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 127, 19))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 128, 3))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 128, 3))
|
||||
|
||||
};
|
||||
|
||||
type MyType = {a: string, b: string | undefined}
|
||||
>MyType : Symbol(MyType, Decl(keyofAndIndexedAccessErrors.ts, 129, 2))
|
||||
>a : Symbol(a, Decl(keyofAndIndexedAccessErrors.ts, 131, 15))
|
||||
>b : Symbol(b, Decl(keyofAndIndexedAccessErrors.ts, 131, 25))
|
||||
|
||||
type Result1 = UndefinedKeys<MyType>;
|
||||
>Result1 : Symbol(Result1, Decl(keyofAndIndexedAccessErrors.ts, 131, 48))
|
||||
>UndefinedKeys : Symbol(UndefinedKeys, Decl(keyofAndIndexedAccessErrors.ts, 123, 1))
|
||||
>MyType : Symbol(MyType, Decl(keyofAndIndexedAccessErrors.ts, 129, 2))
|
||||
|
||||
const a1: Result1['a'] = 'a'; // Error
|
||||
>a1 : Symbol(a1, Decl(keyofAndIndexedAccessErrors.ts, 135, 5))
|
||||
>Result1 : Symbol(Result1, Decl(keyofAndIndexedAccessErrors.ts, 131, 48))
|
||||
|
||||
const b1: Result1['b'] = 'b';
|
||||
>b1 : Symbol(b1, Decl(keyofAndIndexedAccessErrors.ts, 136, 5))
|
||||
>Result1 : Symbol(Result1, Decl(keyofAndIndexedAccessErrors.ts, 131, 48))
|
||||
|
||||
function test1<T extends Record<string, any>, K extends keyof T>(t: T, k: K) {
|
||||
>test1 : Symbol(test1, Decl(keyofAndIndexedAccessErrors.ts, 136, 29))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 138, 15))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 138, 45))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 138, 15))
|
||||
>t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 138, 65))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 138, 15))
|
||||
>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 138, 70))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 138, 45))
|
||||
|
||||
t[k] = 42; // Error
|
||||
>t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 138, 65))
|
||||
>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 138, 70))
|
||||
|
||||
t[k] = "hello"; // Error
|
||||
>t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 138, 65))
|
||||
>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 138, 70))
|
||||
|
||||
t[k] = [10, 20]; // Error
|
||||
>t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 138, 65))
|
||||
>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 138, 70))
|
||||
}
|
||||
|
||||
|
||||
@ -412,3 +412,56 @@ function f4<T extends { [K in keyof T]: string }>(k: keyof T) {
|
||||
>"hello" : "hello"
|
||||
}
|
||||
|
||||
// Repro from #27470
|
||||
|
||||
type UndefinedKeys<T extends Record<string, any>> = {
|
||||
>UndefinedKeys : UndefinedKeys<T>
|
||||
|
||||
[K in keyof T]: undefined extends T[K] ? K : never
|
||||
};
|
||||
|
||||
type MyType = {a: string, b: string | undefined}
|
||||
>MyType : MyType
|
||||
>a : string
|
||||
>b : string
|
||||
|
||||
type Result1 = UndefinedKeys<MyType>;
|
||||
>Result1 : UndefinedKeys<MyType>
|
||||
|
||||
const a1: Result1['a'] = 'a'; // Error
|
||||
>a1 : "a"
|
||||
>'a' : "a"
|
||||
|
||||
const b1: Result1['b'] = 'b';
|
||||
>b1 : "b"
|
||||
>'b' : "b"
|
||||
|
||||
function test1<T extends Record<string, any>, K extends keyof T>(t: T, k: K) {
|
||||
>test1 : <T extends Record<string, any>, K extends keyof T>(t: T, k: K) => void
|
||||
>t : T
|
||||
>k : K
|
||||
|
||||
t[k] = 42; // Error
|
||||
>t[k] = 42 : 42
|
||||
>t[k] : T[K]
|
||||
>t : T
|
||||
>k : K
|
||||
>42 : 42
|
||||
|
||||
t[k] = "hello"; // Error
|
||||
>t[k] = "hello" : "hello"
|
||||
>t[k] : T[K]
|
||||
>t : T
|
||||
>k : K
|
||||
>"hello" : "hello"
|
||||
|
||||
t[k] = [10, 20]; // Error
|
||||
>t[k] = [10, 20] : number[]
|
||||
>t[k] : T[K]
|
||||
>t : T
|
||||
>k : K
|
||||
>[10, 20] : number[]
|
||||
>10 : 10
|
||||
>20 : 20
|
||||
}
|
||||
|
||||
|
||||
@ -3,13 +3,11 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessTy
|
||||
tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessType.ts(9,5): error TS2322: Type 'string' is not assignable to type 'T[P]'.
|
||||
tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessType.ts(12,5): error TS2322: Type 'string' is not assignable to type 'T[P]'.
|
||||
tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessType.ts(15,5): error TS2322: Type 'string' is not assignable to type 'T[P]'.
|
||||
Type 'string' is not assignable to type 'never'.
|
||||
tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessType.ts(18,5): error TS2322: Type 'string' is not assignable to type 'T[P]'.
|
||||
tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessType.ts(21,5): error TS2322: Type 'string' is not assignable to type 'T[P]'.
|
||||
tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessType.ts(24,5): error TS2322: Type 'string' is not assignable to type 'T[P]'.
|
||||
tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessType.ts(27,5): error TS2322: Type 'string' is not assignable to type 'T[P]'.
|
||||
tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessType.ts(30,5): error TS2322: Type 'string' is not assignable to type 'T[P]'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessType.ts (10 errors) ====
|
||||
@ -38,7 +36,6 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessTy
|
||||
tp = s;
|
||||
~~
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'T[P]'.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'never'.
|
||||
}
|
||||
function k<T extends number, P extends keyof T>(s: string, tp: T[P]): void {
|
||||
tp = s;
|
||||
@ -64,6 +61,5 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveConstraintOfIndexAccessTy
|
||||
tp = s;
|
||||
~~
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'T[P]'.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
}
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
tests/cases/compiler/undefinedAssignableToGenericMappedIntersection.ts(5,5): error TS2322: Type 'undefined' is not assignable to type 'Errors<T>[keyof T]'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/undefinedAssignableToGenericMappedIntersection.ts (1 errors) ====
|
||||
type Errors<T> = { [P in keyof T]: string | undefined } & {all: string | undefined};
|
||||
function foo<T>() {
|
||||
let obj!: Errors<T>
|
||||
let x!: keyof T;
|
||||
obj[x] = undefined;
|
||||
~~~~~~
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'Errors<T>[keyof T]'.
|
||||
}
|
||||
|
||||
@ -302,23 +302,16 @@ type S2 = {
|
||||
b: string;
|
||||
};
|
||||
|
||||
function f90<T extends S2, K extends keyof S2>(x1: S2[keyof S2], x2: T[keyof S2], x3: S2[K], x4: T[K]) {
|
||||
function f90<T extends S2, K extends keyof S2>(x1: S2[keyof S2], x2: T[keyof S2], x3: S2[K]) {
|
||||
x1 = x2;
|
||||
x1 = x3;
|
||||
x1 = x4;
|
||||
x2 = x1;
|
||||
x2 = x3;
|
||||
x2 = x4;
|
||||
x3 = x1;
|
||||
x3 = x2;
|
||||
x3 = x4;
|
||||
x4 = x1;
|
||||
x4 = x2;
|
||||
x4 = x3;
|
||||
x1.length;
|
||||
x2.length;
|
||||
x3.length;
|
||||
x4.length;
|
||||
}
|
||||
|
||||
function f91<T, K extends keyof T>(x: T, y: T[keyof T], z: T[K]) {
|
||||
|
||||
@ -122,3 +122,22 @@ function f4<T extends { [K in keyof T]: string }>(k: keyof T) {
|
||||
k = 42; // error
|
||||
k = "hello"; // error
|
||||
}
|
||||
|
||||
// Repro from #27470
|
||||
|
||||
type UndefinedKeys<T extends Record<string, any>> = {
|
||||
[K in keyof T]: undefined extends T[K] ? K : never
|
||||
};
|
||||
|
||||
type MyType = {a: string, b: string | undefined}
|
||||
|
||||
type Result1 = UndefinedKeys<MyType>;
|
||||
|
||||
const a1: Result1['a'] = 'a'; // Error
|
||||
const b1: Result1['b'] = 'b';
|
||||
|
||||
function test1<T extends Record<string, any>, K extends keyof T>(t: T, k: K) {
|
||||
t[k] = 42; // Error
|
||||
t[k] = "hello"; // Error
|
||||
t[k] = [10, 20]; // Error
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user