diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 75f8715fca7d0..b94d14d58a5f9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8268,7 +8268,8 @@ namespace ts { } function getIndexType(type: Type, stringsOnly = keyofStringsOnly): Type { - return type.flags & TypeFlags.Intersection ? getUnionType(map((type).types, t => getIndexType(t, stringsOnly))) : + return type.flags & TypeFlags.Union ? getIntersectionType(map((type).types, t => getIndexType(t, stringsOnly))) : + type.flags & TypeFlags.Intersection ? getUnionType(map((type).types, t => getIndexType(t, stringsOnly))) : maybeTypeOfKind(type, TypeFlags.InstantiableNonPrimitive) ? getIndexTypeForGenericType(type, stringsOnly) : getObjectFlags(type) & ObjectFlags.Mapped ? getConstraintTypeFromMappedType(type) : type === wildcardType ? wildcardType : diff --git a/tests/baselines/reference/keyofAndIndexedAccess.js b/tests/baselines/reference/keyofAndIndexedAccess.js index 422cef5a574f4..f0af336563cb1 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.js +++ b/tests/baselines/reference/keyofAndIndexedAccess.js @@ -565,6 +565,24 @@ function f3>(t: T, k: K, tk: T[K]): void { type Predicates = { [T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T] } + +// Repro from #23618 + +type DBBoolTable = { [k in K]: 0 | 1 } +enum Flag { + FLAG_1 = "flag_1", + FLAG_2 = "flag_2" +} + +type SimpleDBRecord = { staticField: number } & DBBoolTable +function getFlagsFromSimpleRecord(record: SimpleDBRecord, flags: Flag[]) { + return record[flags[0]]; +} + +type DynamicDBRecord = ({ dynamicField: number } | { dynamicField: string }) & DBBoolTable +function getFlagsFromDynamicRecord(record: DynamicDBRecord, flags: Flag[]) { + return record[flags[0]]; +} //// [keyofAndIndexedAccess.js] @@ -948,6 +966,17 @@ function f3(t, k, tk) { t[key] = tk; // ok, T[K] ==> T[keyof T] } } +var Flag; +(function (Flag) { + Flag["FLAG_1"] = "flag_1"; + Flag["FLAG_2"] = "flag_2"; +})(Flag || (Flag = {})); +function getFlagsFromSimpleRecord(record, flags) { + return record[flags[0]]; +} +function getFlagsFromDynamicRecord(record, flags) { + return record[flags[0]]; +} //// [keyofAndIndexedAccess.d.ts] @@ -1212,3 +1241,20 @@ declare function f3>(t: T, k: K, tk: T[K]) declare type Predicates = { [T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T]; }; +declare type DBBoolTable = { + [k in K]: 0 | 1; +}; +declare enum Flag { + FLAG_1 = "flag_1", + FLAG_2 = "flag_2" +} +declare type SimpleDBRecord = { + staticField: number; +} & DBBoolTable; +declare function getFlagsFromSimpleRecord(record: SimpleDBRecord, flags: Flag[]): SimpleDBRecord[Flag]; +declare type DynamicDBRecord = ({ + dynamicField: number; +} | { + dynamicField: string; +}) & DBBoolTable; +declare function getFlagsFromDynamicRecord(record: DynamicDBRecord, flags: Flag[]): DynamicDBRecord[Flag]; diff --git a/tests/baselines/reference/keyofAndIndexedAccess.symbols b/tests/baselines/reference/keyofAndIndexedAccess.symbols index b1206a4938851..27c7128e42dc8 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.symbols +++ b/tests/baselines/reference/keyofAndIndexedAccess.symbols @@ -2010,3 +2010,64 @@ type Predicates = { >T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 564, 3)) } +// Repro from #23618 + +type DBBoolTable = { [k in K]: 0 | 1 } +>DBBoolTable : Symbol(DBBoolTable, Decl(keyofAndIndexedAccess.ts, 565, 1)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 569, 17)) +>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 569, 40)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 569, 17)) + +enum Flag { +>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 569, 56)) + + FLAG_1 = "flag_1", +>FLAG_1 : Symbol(Flag.FLAG_1, Decl(keyofAndIndexedAccess.ts, 570, 11)) + + FLAG_2 = "flag_2" +>FLAG_2 : Symbol(Flag.FLAG_2, Decl(keyofAndIndexedAccess.ts, 571, 22)) +} + +type SimpleDBRecord = { staticField: number } & DBBoolTable +>SimpleDBRecord : Symbol(SimpleDBRecord, Decl(keyofAndIndexedAccess.ts, 573, 1)) +>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 575, 20)) +>staticField : Symbol(staticField, Decl(keyofAndIndexedAccess.ts, 575, 44)) +>DBBoolTable : Symbol(DBBoolTable, Decl(keyofAndIndexedAccess.ts, 565, 1)) +>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 575, 20)) + +function getFlagsFromSimpleRecord(record: SimpleDBRecord, flags: Flag[]) { +>getFlagsFromSimpleRecord : Symbol(getFlagsFromSimpleRecord, Decl(keyofAndIndexedAccess.ts, 575, 86)) +>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 576, 34)) +>record : Symbol(record, Decl(keyofAndIndexedAccess.ts, 576, 55)) +>SimpleDBRecord : Symbol(SimpleDBRecord, Decl(keyofAndIndexedAccess.ts, 573, 1)) +>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 576, 34)) +>flags : Symbol(flags, Decl(keyofAndIndexedAccess.ts, 576, 84)) +>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 576, 34)) + + return record[flags[0]]; +>record : Symbol(record, Decl(keyofAndIndexedAccess.ts, 576, 55)) +>flags : Symbol(flags, Decl(keyofAndIndexedAccess.ts, 576, 84)) +} + +type DynamicDBRecord = ({ dynamicField: number } | { dynamicField: string }) & DBBoolTable +>DynamicDBRecord : Symbol(DynamicDBRecord, Decl(keyofAndIndexedAccess.ts, 578, 1)) +>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 580, 21)) +>dynamicField : Symbol(dynamicField, Decl(keyofAndIndexedAccess.ts, 580, 46)) +>dynamicField : Symbol(dynamicField, Decl(keyofAndIndexedAccess.ts, 580, 73)) +>DBBoolTable : Symbol(DBBoolTable, Decl(keyofAndIndexedAccess.ts, 565, 1)) +>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 580, 21)) + +function getFlagsFromDynamicRecord(record: DynamicDBRecord, flags: Flag[]) { +>getFlagsFromDynamicRecord : Symbol(getFlagsFromDynamicRecord, Decl(keyofAndIndexedAccess.ts, 580, 117)) +>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 581, 35)) +>record : Symbol(record, Decl(keyofAndIndexedAccess.ts, 581, 56)) +>DynamicDBRecord : Symbol(DynamicDBRecord, Decl(keyofAndIndexedAccess.ts, 578, 1)) +>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 581, 35)) +>flags : Symbol(flags, Decl(keyofAndIndexedAccess.ts, 581, 86)) +>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 581, 35)) + + return record[flags[0]]; +>record : Symbol(record, Decl(keyofAndIndexedAccess.ts, 581, 56)) +>flags : Symbol(flags, Decl(keyofAndIndexedAccess.ts, 581, 86)) +} + diff --git a/tests/baselines/reference/keyofAndIndexedAccess.types b/tests/baselines/reference/keyofAndIndexedAccess.types index 4e41b58e66457..de35c620d3318 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.types +++ b/tests/baselines/reference/keyofAndIndexedAccess.types @@ -890,11 +890,11 @@ function f60(source: T, target: T) { } function f70(func: (k1: keyof (T | U), k2: keyof (T & U)) => void) { ->f70 : (func: (k1: keyof (T | U), k2: keyof T | keyof U) => void) => void ->func : (k1: keyof (T | U), k2: keyof T | keyof U) => void +>f70 : (func: (k1: keyof T & keyof U, k2: keyof T | keyof U) => void) => void +>func : (k1: keyof T & keyof U, k2: keyof T | keyof U) => void >T : T >U : U ->k1 : keyof (T | U) +>k1 : keyof T & keyof U >T : T >U : U >k2 : keyof T | keyof U @@ -903,7 +903,7 @@ function f70(func: (k1: keyof (T | U), k2: keyof (T & U)) => void) { func<{ a: any, b: any }, { a: any, c: any }>('a', 'a'); >func<{ a: any, b: any }, { a: any, c: any }>('a', 'a') : void ->func : (k1: keyof (T | U), k2: keyof T | keyof U) => void +>func : (k1: keyof T & keyof U, k2: keyof T | keyof U) => void >a : any >b : any >a : any @@ -913,7 +913,7 @@ function f70(func: (k1: keyof (T | U), k2: keyof (T & U)) => void) { func<{ a: any, b: any }, { a: any, c: any }>('a', 'b'); >func<{ a: any, b: any }, { a: any, c: any }>('a', 'b') : void ->func : (k1: keyof (T | U), k2: keyof T | keyof U) => void +>func : (k1: keyof T & keyof U, k2: keyof T | keyof U) => void >a : any >b : any >a : any @@ -923,7 +923,7 @@ function f70(func: (k1: keyof (T | U), k2: keyof (T & U)) => void) { func<{ a: any, b: any }, { a: any, c: any }>('a', 'c'); >func<{ a: any, b: any }, { a: any, c: any }>('a', 'c') : void ->func : (k1: keyof (T | U), k2: keyof T | keyof U) => void +>func : (k1: keyof T & keyof U, k2: keyof T | keyof U) => void >a : any >b : any >a : any @@ -1097,8 +1097,8 @@ function f73(func: (x: T, y: U, k: K) => (T & U)[ } function f74(func: (x: T, y: U, k: K) => (T | U)[K]) { ->f74 : (func: (x: T, y: U, k: K) => (T | U)[K]) => void ->func : (x: T, y: U, k: K) => (T | U)[K] +>f74 : (func: (x: T, y: U, k: K) => (T | U)[K]) => void +>func : (x: T, y: U, k: K) => (T | U)[K] >T : T >U : U >K : K @@ -1117,7 +1117,7 @@ function f74(func: (x: T, y: U, k: K) => (T | U)[ let a = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'a'); // number >a : number >func({ a: 1, b: "hello" }, { a: 2, b: true }, 'a') : number ->func : (x: T, y: U, k: K) => (T | U)[K] +>func : (x: T, y: U, k: K) => (T | U)[K] >{ a: 1, b: "hello" } : { a: number; b: string; } >a : number >1 : 1 @@ -1133,7 +1133,7 @@ function f74(func: (x: T, y: U, k: K) => (T | U)[ let b = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'b'); // string | boolean >b : string | boolean >func({ a: 1, b: "hello" }, { a: 2, b: true }, 'b') : string | boolean ->func : (x: T, y: U, k: K) => (T | U)[K] +>func : (x: T, y: U, k: K) => (T | U)[K] >{ a: 1, b: "hello" } : { a: number; b: string; } >a : number >1 : 1 @@ -2345,3 +2345,72 @@ type Predicates = { >T : T } +// Repro from #23618 + +type DBBoolTable = { [k in K]: 0 | 1 } +>DBBoolTable : DBBoolTable +>K : K +>k : k +>K : K + +enum Flag { +>Flag : Flag + + FLAG_1 = "flag_1", +>FLAG_1 : Flag.FLAG_1 +>"flag_1" : "flag_1" + + FLAG_2 = "flag_2" +>FLAG_2 : Flag.FLAG_2 +>"flag_2" : "flag_2" +} + +type SimpleDBRecord = { staticField: number } & DBBoolTable +>SimpleDBRecord : SimpleDBRecord +>Flag : Flag +>staticField : number +>DBBoolTable : DBBoolTable +>Flag : Flag + +function getFlagsFromSimpleRecord(record: SimpleDBRecord, flags: Flag[]) { +>getFlagsFromSimpleRecord : (record: SimpleDBRecord, flags: Flag[]) => SimpleDBRecord[Flag] +>Flag : Flag +>record : SimpleDBRecord +>SimpleDBRecord : SimpleDBRecord +>Flag : Flag +>flags : Flag[] +>Flag : Flag + + return record[flags[0]]; +>record[flags[0]] : SimpleDBRecord[Flag] +>record : SimpleDBRecord +>flags[0] : Flag +>flags : Flag[] +>0 : 0 +} + +type DynamicDBRecord = ({ dynamicField: number } | { dynamicField: string }) & DBBoolTable +>DynamicDBRecord : DynamicDBRecord +>Flag : Flag +>dynamicField : number +>dynamicField : string +>DBBoolTable : DBBoolTable +>Flag : Flag + +function getFlagsFromDynamicRecord(record: DynamicDBRecord, flags: Flag[]) { +>getFlagsFromDynamicRecord : (record: DynamicDBRecord, flags: Flag[]) => DynamicDBRecord[Flag] +>Flag : Flag +>record : DynamicDBRecord +>DynamicDBRecord : DynamicDBRecord +>Flag : Flag +>flags : Flag[] +>Flag : Flag + + return record[flags[0]]; +>record[flags[0]] : DynamicDBRecord[Flag] +>record : DynamicDBRecord +>flags[0] : Flag +>flags : Flag[] +>0 : 0 +} + diff --git a/tests/baselines/reference/keyofAndIndexedAccessErrors.errors.txt b/tests/baselines/reference/keyofAndIndexedAccessErrors.errors.txt index f9bb63c43b1ee..bbd4685a4923d 100644 --- a/tests/baselines/reference/keyofAndIndexedAccessErrors.errors.txt +++ b/tests/baselines/reference/keyofAndIndexedAccessErrors.errors.txt @@ -22,33 +22,44 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(64,33): error tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(66,24): error TS2345: Argument of type '"size"' is not assignable to parameter of type '"name" | "width" | "height" | "visible"'. tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(67,24): error TS2345: Argument of type '"name" | "size"' is not assignable to parameter of type '"name" | "width" | "height" | "visible"'. Type '"size"' is not assignable to type '"name" | "width" | "height" | "visible"'. -tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(72,5): error TS2536: Type 'keyof T | keyof U' cannot be used to index type 'T | U'. -tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(76,5): error TS2322: Type 'T | U' is not assignable to type 'T & U'. - Type 'T' is not assignable to type 'T & U'. - Type 'T' is not assignable to type 'U'. -tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(77,5): error TS2322: Type 'keyof T | keyof U' is not assignable to type 'keyof (T | U)'. - Type 'keyof T' is not assignable to type 'keyof (T | U)'. - Type 'string | number | symbol' is not assignable to type 'keyof (T | U)'. - Type 'string' is not assignable to type 'keyof (T | U)'. -tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(86,9): error TS2322: Type 'Extract' is not assignable to type 'K'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(73,5): error TS2536: Type 'keyof T | keyof U' cannot be used to index type 'T | U'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(74,5): error TS2536: Type 'keyof T | keyof U' cannot be used to index type 'T | U'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(82,5): error TS2322: Type 'keyof T | keyof U' is not assignable to type 'keyof T & keyof U'. + Type 'keyof T' is not assignable to type 'keyof T & keyof U'. + Type 'string | number | symbol' is not assignable to type 'keyof T & keyof U'. + Type 'string' is not assignable to type 'keyof T & keyof U'. + Type 'string' is not assignable to type 'keyof T'. + Type 'keyof T' is not assignable to type 'keyof U'. + Type 'string | number | symbol' is not assignable to type 'keyof U'. + Type 'string' is not assignable to type 'keyof U'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(83,5): error TS2322: Type 'keyof T | keyof U' is not assignable to type 'keyof T & keyof U'. + Type 'keyof T' is not assignable to type 'keyof T & keyof U'. + Type 'keyof T' is not assignable to type 'keyof U'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(86,5): error TS2322: Type 'keyof T | keyof U' is not assignable to type 'keyof T & keyof U'. + Type 'keyof T' is not assignable to type 'keyof T & keyof U'. + Type 'keyof T' is not assignable to type 'keyof U'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(87,5): error TS2322: Type 'keyof T | keyof U' is not assignable to type 'keyof T & keyof U'. + Type 'keyof T' is not assignable to type 'keyof T & keyof U'. + Type 'keyof T' is not assignable to type 'keyof U'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(103,9): error TS2322: Type 'Extract' is not assignable to type 'K'. Type 'string & keyof T' is not assignable to type 'K'. Type 'string' is not assignable to type 'K'. -tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(88,9): error TS2322: Type 'T[Extract]' is not assignable to type 'T[K]'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(105,9): error TS2322: Type 'T[Extract]' is not assignable to type 'T[K]'. Type 'Extract' is not assignable to type 'K'. -tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(91,5): error TS2322: Type 'T[K]' is not assignable to type 'U[K]'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(108,5): error TS2322: Type 'T[K]' is not assignable to type 'U[K]'. Type 'T' is not assignable to type 'U'. -tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(94,5): error TS2322: Type 'T[J]' is not assignable to type 'U[J]'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(111,5): error TS2322: Type 'T[J]' is not assignable to type 'U[J]'. Type 'T' is not assignable to type 'U'. -tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(97,5): error TS2322: Type 'T[K]' is not assignable to type 'T[J]'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(114,5): error TS2322: Type 'T[K]' is not assignable to type 'T[J]'. Type 'K' is not assignable to type 'J'. Type 'Extract' is not assignable to type 'J'. Type 'string & keyof T' is not assignable to type 'J'. Type 'string' is not assignable to type 'J'. -tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(100,5): error TS2322: Type 'T[K]' is not assignable to type 'U[J]'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(117,5): error TS2322: Type 'T[K]' is not assignable to type 'U[J]'. Type 'T' is not assignable to type 'U'. -==== tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts (31 errors) ==== +==== tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts (34 errors) ==== class Shape { name: string; width: number; @@ -164,26 +175,57 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(100,5): error !!! error TS2345: Type '"size"' is not assignable to type '"name" | "width" | "height" | "visible"'. } - function f20(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) { - o1[k1]; - o1[k2]; // Error - ~~~~~~ + function f20(x: T | U, y: T & U, k1: keyof (T | U), k2: keyof T & keyof U, k3: keyof (T & U), k4: keyof T | keyof U) { + x[k1]; + x[k2]; + x[k3]; // Error + ~~~~~ !!! error TS2536: Type 'keyof T | keyof U' cannot be used to index type 'T | U'. - o2[k1]; - o2[k2]; - o1 = o2; - o2 = o1; // Error + x[k4]; // Error + ~~~~~ +!!! error TS2536: Type 'keyof T | keyof U' cannot be used to index type 'T | U'. + + y[k1]; + y[k2]; + y[k3]; + y[k4]; + + k1 = k2; + k1 = k3; // Error ~~ -!!! error TS2322: Type 'T | U' is not assignable to type 'T & U'. -!!! error TS2322: Type 'T' is not assignable to type 'T & U'. -!!! error TS2322: Type 'T' is not assignable to type 'U'. - k1 = k2; // Error +!!! error TS2322: Type 'keyof T | keyof U' is not assignable to type 'keyof T & keyof U'. +!!! error TS2322: Type 'keyof T' is not assignable to type 'keyof T & keyof U'. +!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'keyof T & keyof U'. +!!! error TS2322: Type 'string' is not assignable to type 'keyof T & keyof U'. +!!! error TS2322: Type 'string' is not assignable to type 'keyof T'. +!!! error TS2322: Type 'keyof T' is not assignable to type 'keyof U'. +!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'keyof U'. +!!! error TS2322: Type 'string' is not assignable to type 'keyof U'. + k1 = k4; // Error ~~ -!!! error TS2322: Type 'keyof T | keyof U' is not assignable to type 'keyof (T | U)'. -!!! error TS2322: Type 'keyof T' is not assignable to type 'keyof (T | U)'. -!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'keyof (T | U)'. -!!! error TS2322: Type 'string' is not assignable to type 'keyof (T | U)'. +!!! error TS2322: Type 'keyof T | keyof U' is not assignable to type 'keyof T & keyof U'. +!!! error TS2322: Type 'keyof T' is not assignable to type 'keyof T & keyof U'. +!!! error TS2322: Type 'keyof T' is not assignable to type 'keyof U'. + k2 = k1; + k2 = k3; // Error + ~~ +!!! error TS2322: Type 'keyof T | keyof U' is not assignable to type 'keyof T & keyof U'. +!!! error TS2322: Type 'keyof T' is not assignable to type 'keyof T & keyof U'. +!!! error TS2322: Type 'keyof T' is not assignable to type 'keyof U'. + k2 = k4; // Error + ~~ +!!! error TS2322: Type 'keyof T | keyof U' is not assignable to type 'keyof T & keyof U'. +!!! error TS2322: Type 'keyof T' is not assignable to type 'keyof T & keyof U'. +!!! error TS2322: Type 'keyof T' is not assignable to type 'keyof U'. + + k3 = k1; + k3 = k2; + k3 = k4; + + k4 = k1; + k4 = k2; + k4 = k3; } // Repro from #17166 diff --git a/tests/baselines/reference/keyofAndIndexedAccessErrors.js b/tests/baselines/reference/keyofAndIndexedAccessErrors.js index 0f026d5d2e59f..c64f4df533178 100644 --- a/tests/baselines/reference/keyofAndIndexedAccessErrors.js +++ b/tests/baselines/reference/keyofAndIndexedAccessErrors.js @@ -68,15 +68,32 @@ function f10(shape: Shape) { setProperty(shape, cond ? "name" : "size", 10); // Error } -function f20(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) { - o1[k1]; - o1[k2]; // Error - o2[k1]; - o2[k2]; - o1 = o2; - o2 = o1; // Error - k1 = k2; // Error +function f20(x: T | U, y: T & U, k1: keyof (T | U), k2: keyof T & keyof U, k3: keyof (T & U), k4: keyof T | keyof U) { + x[k1]; + x[k2]; + x[k3]; // Error + x[k4]; // Error + + y[k1]; + y[k2]; + y[k3]; + y[k4]; + + k1 = k2; + k1 = k3; // Error + k1 = k4; // Error + k2 = k1; + k2 = k3; // Error + k2 = k4; // Error + + k3 = k1; + k3 = k2; + k3 = k4; + + k4 = k1; + k4 = k2; + k4 = k3; } // Repro from #17166 @@ -122,15 +139,27 @@ function f10(shape) { setProperty(shape, "size", 10); // Error setProperty(shape, cond ? "name" : "size", 10); // Error } -function f20(k1, k2, o1, o2) { - o1[k1]; - o1[k2]; // Error - o2[k1]; - o2[k2]; - o1 = o2; - o2 = o1; // Error - k1 = k2; // Error +function f20(x, y, k1, k2, k3, k4) { + x[k1]; + x[k2]; + x[k3]; // Error + x[k4]; // Error + y[k1]; + y[k2]; + y[k3]; + y[k4]; + k1 = k2; + k1 = k3; // Error + k1 = k4; // Error k2 = k1; + k2 = k3; // Error + k2 = k4; // Error + k3 = k1; + k3 = k2; + k3 = k4; + k4 = k1; + k4 = k2; + k4 = k3; } // Repro from #17166 function f3(t, k, tk, u, j, uk, tj, uj) { diff --git a/tests/baselines/reference/keyofAndIndexedAccessErrors.symbols b/tests/baselines/reference/keyofAndIndexedAccessErrors.symbols index d062677fa0286..bb86bf68bee32 100644 --- a/tests/baselines/reference/keyofAndIndexedAccessErrors.symbols +++ b/tests/baselines/reference/keyofAndIndexedAccessErrors.symbols @@ -219,142 +219,196 @@ function f10(shape: Shape) { >cond : Symbol(cond, Decl(keyofAndIndexedAccessErrors.ts, 50, 11)) } -function f20(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) { +function f20(x: T | U, y: T & U, k1: keyof (T | U), k2: keyof T & keyof U, k3: keyof (T & U), k4: keyof T | keyof U) { >f20 : Symbol(f20, Decl(keyofAndIndexedAccessErrors.ts, 67, 1)) >T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 69, 13)) >U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 69, 15)) ->k1 : Symbol(k1, Decl(keyofAndIndexedAccessErrors.ts, 69, 19)) +>x : Symbol(x, Decl(keyofAndIndexedAccessErrors.ts, 69, 19)) >T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 69, 13)) >U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 69, 15)) ->k2 : Symbol(k2, Decl(keyofAndIndexedAccessErrors.ts, 69, 37)) +>y : Symbol(y, Decl(keyofAndIndexedAccessErrors.ts, 69, 28)) >T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 69, 13)) >U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 69, 15)) ->o1 : Symbol(o1, Decl(keyofAndIndexedAccessErrors.ts, 69, 56)) +>k1 : Symbol(k1, Decl(keyofAndIndexedAccessErrors.ts, 69, 38)) >T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 69, 13)) >U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 69, 15)) ->o2 : Symbol(o2, Decl(keyofAndIndexedAccessErrors.ts, 69, 67)) +>k2 : Symbol(k2, Decl(keyofAndIndexedAccessErrors.ts, 69, 57)) >T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 69, 13)) >U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 69, 15)) +>k3 : Symbol(k3, Decl(keyofAndIndexedAccessErrors.ts, 69, 80)) +>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 69, 13)) +>U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 69, 15)) +>k4 : Symbol(k4, Decl(keyofAndIndexedAccessErrors.ts, 69, 99)) +>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 69, 13)) +>U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 69, 15)) + + x[k1]; +>x : Symbol(x, Decl(keyofAndIndexedAccessErrors.ts, 69, 19)) +>k1 : Symbol(k1, Decl(keyofAndIndexedAccessErrors.ts, 69, 38)) + + x[k2]; +>x : Symbol(x, Decl(keyofAndIndexedAccessErrors.ts, 69, 19)) +>k2 : Symbol(k2, Decl(keyofAndIndexedAccessErrors.ts, 69, 57)) + + x[k3]; // Error +>x : Symbol(x, Decl(keyofAndIndexedAccessErrors.ts, 69, 19)) +>k3 : Symbol(k3, Decl(keyofAndIndexedAccessErrors.ts, 69, 80)) + + x[k4]; // Error +>x : Symbol(x, Decl(keyofAndIndexedAccessErrors.ts, 69, 19)) +>k4 : Symbol(k4, Decl(keyofAndIndexedAccessErrors.ts, 69, 99)) - o1[k1]; ->o1 : Symbol(o1, Decl(keyofAndIndexedAccessErrors.ts, 69, 56)) ->k1 : Symbol(k1, Decl(keyofAndIndexedAccessErrors.ts, 69, 19)) + y[k1]; +>y : Symbol(y, Decl(keyofAndIndexedAccessErrors.ts, 69, 28)) +>k1 : Symbol(k1, Decl(keyofAndIndexedAccessErrors.ts, 69, 38)) - o1[k2]; // Error ->o1 : Symbol(o1, Decl(keyofAndIndexedAccessErrors.ts, 69, 56)) ->k2 : Symbol(k2, Decl(keyofAndIndexedAccessErrors.ts, 69, 37)) + y[k2]; +>y : Symbol(y, Decl(keyofAndIndexedAccessErrors.ts, 69, 28)) +>k2 : Symbol(k2, Decl(keyofAndIndexedAccessErrors.ts, 69, 57)) - o2[k1]; ->o2 : Symbol(o2, Decl(keyofAndIndexedAccessErrors.ts, 69, 67)) ->k1 : Symbol(k1, Decl(keyofAndIndexedAccessErrors.ts, 69, 19)) + y[k3]; +>y : Symbol(y, Decl(keyofAndIndexedAccessErrors.ts, 69, 28)) +>k3 : Symbol(k3, Decl(keyofAndIndexedAccessErrors.ts, 69, 80)) - o2[k2]; ->o2 : Symbol(o2, Decl(keyofAndIndexedAccessErrors.ts, 69, 67)) ->k2 : Symbol(k2, Decl(keyofAndIndexedAccessErrors.ts, 69, 37)) + y[k4]; +>y : Symbol(y, Decl(keyofAndIndexedAccessErrors.ts, 69, 28)) +>k4 : Symbol(k4, Decl(keyofAndIndexedAccessErrors.ts, 69, 99)) - o1 = o2; ->o1 : Symbol(o1, Decl(keyofAndIndexedAccessErrors.ts, 69, 56)) ->o2 : Symbol(o2, Decl(keyofAndIndexedAccessErrors.ts, 69, 67)) + k1 = k2; +>k1 : Symbol(k1, Decl(keyofAndIndexedAccessErrors.ts, 69, 38)) +>k2 : Symbol(k2, Decl(keyofAndIndexedAccessErrors.ts, 69, 57)) - o2 = o1; // Error ->o2 : Symbol(o2, Decl(keyofAndIndexedAccessErrors.ts, 69, 67)) ->o1 : Symbol(o1, Decl(keyofAndIndexedAccessErrors.ts, 69, 56)) + k1 = k3; // Error +>k1 : Symbol(k1, Decl(keyofAndIndexedAccessErrors.ts, 69, 38)) +>k3 : Symbol(k3, Decl(keyofAndIndexedAccessErrors.ts, 69, 80)) - k1 = k2; // Error ->k1 : Symbol(k1, Decl(keyofAndIndexedAccessErrors.ts, 69, 19)) ->k2 : Symbol(k2, Decl(keyofAndIndexedAccessErrors.ts, 69, 37)) + k1 = k4; // Error +>k1 : Symbol(k1, Decl(keyofAndIndexedAccessErrors.ts, 69, 38)) +>k4 : Symbol(k4, Decl(keyofAndIndexedAccessErrors.ts, 69, 99)) k2 = k1; ->k2 : Symbol(k2, Decl(keyofAndIndexedAccessErrors.ts, 69, 37)) ->k1 : Symbol(k1, Decl(keyofAndIndexedAccessErrors.ts, 69, 19)) +>k2 : Symbol(k2, Decl(keyofAndIndexedAccessErrors.ts, 69, 57)) +>k1 : Symbol(k1, Decl(keyofAndIndexedAccessErrors.ts, 69, 38)) + + k2 = k3; // Error +>k2 : Symbol(k2, Decl(keyofAndIndexedAccessErrors.ts, 69, 57)) +>k3 : Symbol(k3, Decl(keyofAndIndexedAccessErrors.ts, 69, 80)) + + k2 = k4; // Error +>k2 : Symbol(k2, Decl(keyofAndIndexedAccessErrors.ts, 69, 57)) +>k4 : Symbol(k4, Decl(keyofAndIndexedAccessErrors.ts, 69, 99)) + + k3 = k1; +>k3 : Symbol(k3, Decl(keyofAndIndexedAccessErrors.ts, 69, 80)) +>k1 : Symbol(k1, Decl(keyofAndIndexedAccessErrors.ts, 69, 38)) + + k3 = k2; +>k3 : Symbol(k3, Decl(keyofAndIndexedAccessErrors.ts, 69, 80)) +>k2 : Symbol(k2, Decl(keyofAndIndexedAccessErrors.ts, 69, 57)) + + k3 = k4; +>k3 : Symbol(k3, Decl(keyofAndIndexedAccessErrors.ts, 69, 80)) +>k4 : Symbol(k4, Decl(keyofAndIndexedAccessErrors.ts, 69, 99)) + + k4 = k1; +>k4 : Symbol(k4, Decl(keyofAndIndexedAccessErrors.ts, 69, 99)) +>k1 : Symbol(k1, Decl(keyofAndIndexedAccessErrors.ts, 69, 38)) + + k4 = k2; +>k4 : Symbol(k4, Decl(keyofAndIndexedAccessErrors.ts, 69, 99)) +>k2 : Symbol(k2, Decl(keyofAndIndexedAccessErrors.ts, 69, 57)) + + k4 = k3; +>k4 : Symbol(k4, Decl(keyofAndIndexedAccessErrors.ts, 69, 99)) +>k3 : Symbol(k3, Decl(keyofAndIndexedAccessErrors.ts, 69, 80)) } // Repro from #17166 function f3, U extends T, J extends K>( ->f3 : Symbol(f3, Decl(keyofAndIndexedAccessErrors.ts, 78, 1)) ->T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12)) ->K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 81, 14)) +>f3 : Symbol(f3, Decl(keyofAndIndexedAccessErrors.ts, 95, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 98, 12)) +>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 98, 14)) >Extract : Symbol(Extract, Decl(lib.d.ts, --, --)) ->T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12)) ->U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 81, 50)) ->T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12)) ->J : Symbol(J, Decl(keyofAndIndexedAccessErrors.ts, 81, 63)) ->K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 81, 14)) +>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 98, 12)) +>U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 98, 50)) +>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 98, 12)) +>J : Symbol(J, Decl(keyofAndIndexedAccessErrors.ts, 98, 63)) +>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 98, 14)) t: T, k: K, tk: T[K], u: U, j: J, uk: U[K], tj: T[J], uj: U[J]): void { ->t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 81, 77)) ->T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12)) ->k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 82, 9)) ->K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 81, 14)) ->tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15)) ->T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12)) ->K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 81, 14)) ->u : Symbol(u, Decl(keyofAndIndexedAccessErrors.ts, 82, 25)) ->U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 81, 50)) ->j : Symbol(j, Decl(keyofAndIndexedAccessErrors.ts, 82, 31)) ->J : Symbol(J, Decl(keyofAndIndexedAccessErrors.ts, 81, 63)) ->uk : Symbol(uk, Decl(keyofAndIndexedAccessErrors.ts, 82, 37)) ->U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 81, 50)) ->K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 81, 14)) ->tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 82, 47)) ->T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12)) ->J : Symbol(J, Decl(keyofAndIndexedAccessErrors.ts, 81, 63)) ->uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 82, 57)) ->U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 81, 50)) ->J : Symbol(J, Decl(keyofAndIndexedAccessErrors.ts, 81, 63)) +>t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 98, 77)) +>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 98, 12)) +>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 99, 9)) +>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 98, 14)) +>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 99, 15)) +>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 98, 12)) +>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 98, 14)) +>u : Symbol(u, Decl(keyofAndIndexedAccessErrors.ts, 99, 25)) +>U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 98, 50)) +>j : Symbol(j, Decl(keyofAndIndexedAccessErrors.ts, 99, 31)) +>J : Symbol(J, Decl(keyofAndIndexedAccessErrors.ts, 98, 63)) +>uk : Symbol(uk, Decl(keyofAndIndexedAccessErrors.ts, 99, 37)) +>U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 98, 50)) +>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 98, 14)) +>tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 99, 47)) +>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 98, 12)) +>J : Symbol(J, Decl(keyofAndIndexedAccessErrors.ts, 98, 63)) +>uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 99, 57)) +>U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 98, 50)) +>J : Symbol(J, Decl(keyofAndIndexedAccessErrors.ts, 98, 63)) for (let key in t) { ->key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 83, 12)) ->t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 81, 77)) +>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 100, 12)) +>t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 98, 77)) key = k // ok, K ==> keyof T ->key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 83, 12)) ->k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 82, 9)) +>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 100, 12)) +>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 99, 9)) k = key // error, keyof T =/=> K ->k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 82, 9)) ->key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 83, 12)) +>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 99, 9)) +>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 100, 12)) t[key] = tk; // ok, T[K] ==> T[keyof T] ->t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 81, 77)) ->key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 83, 12)) ->tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15)) +>t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 98, 77)) +>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 100, 12)) +>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 99, 15)) tk = t[key]; // error, T[keyof T] =/=> T[K] ->tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15)) ->t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 81, 77)) ->key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 83, 12)) +>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 99, 15)) +>t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 98, 77)) +>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 100, 12)) } tk = uk; ->tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15)) ->uk : Symbol(uk, Decl(keyofAndIndexedAccessErrors.ts, 82, 37)) +>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 99, 15)) +>uk : Symbol(uk, Decl(keyofAndIndexedAccessErrors.ts, 99, 37)) uk = tk; // error ->uk : Symbol(uk, Decl(keyofAndIndexedAccessErrors.ts, 82, 37)) ->tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15)) +>uk : Symbol(uk, Decl(keyofAndIndexedAccessErrors.ts, 99, 37)) +>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 99, 15)) tj = uj; ->tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 82, 47)) ->uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 82, 57)) +>tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 99, 47)) +>uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 99, 57)) uj = tj; // error ->uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 82, 57)) ->tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 82, 47)) +>uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 99, 57)) +>tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 99, 47)) tk = tj; ->tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15)) ->tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 82, 47)) +>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 99, 15)) +>tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 99, 47)) tj = tk; // error ->tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 82, 47)) ->tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15)) +>tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 99, 47)) +>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 99, 15)) tk = uj; ->tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15)) ->uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 82, 57)) +>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 99, 15)) +>uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 99, 57)) uj = tk; // error ->uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 82, 57)) ->tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15)) +>uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 99, 57)) +>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 99, 15)) } diff --git a/tests/baselines/reference/keyofAndIndexedAccessErrors.types b/tests/baselines/reference/keyofAndIndexedAccessErrors.types index 2f50ef5c53c8b..6a474c1810729 100644 --- a/tests/baselines/reference/keyofAndIndexedAccessErrors.types +++ b/tests/baselines/reference/keyofAndIndexedAccessErrors.types @@ -34,19 +34,19 @@ type T02 = keyof keyof Object; >Object : Object type T03 = keyof keyof keyof Object; ->T03 : "toString" | "toLocaleString" | "valueOf" +>T03 : "toString" | "valueOf" | ("toString" & number) | ("toLocaleString" & number) | ("valueOf" & number) | ("toFixed" & number) | ("toExponential" & number) | ("toPrecision" & number) >Object : Object type T04 = keyof keyof keyof keyof Object; ->T04 : number | "length" | "toString" | "valueOf" | "charAt" | "charCodeAt" | "concat" | "indexOf" | "lastIndexOf" | "localeCompare" | "match" | "replace" | "search" | "slice" | "split" | "substring" | "toLowerCase" | "toLocaleLowerCase" | "toUpperCase" | "toLocaleUpperCase" | "trim" | "substr" +>T04 : number | "length" | "toString" | "valueOf" | "charAt" | "charCodeAt" | "concat" | "indexOf" | "lastIndexOf" | "localeCompare" | "match" | "replace" | "search" | "slice" | "split" | "substring" | "toLowerCase" | "toLocaleLowerCase" | "toUpperCase" | "toLocaleUpperCase" | "trim" | "substr" | ("toString" & number) | ("valueOf" & number) | (number & "length") | (number & "toString") | (number & "toLocaleString") | (number & "valueOf") | (number & "charAt") | (number & "charCodeAt") | (number & "concat") | (number & "indexOf") | (number & "lastIndexOf") | (number & "localeCompare") | (number & "match") | (number & "replace") | (number & "search") | (number & "slice") | (number & "split") | (number & "substring") | (number & "toLowerCase") | (number & "toLocaleLowerCase") | (number & "toUpperCase") | (number & "toLocaleUpperCase") | (number & "trim") | (number & "substr") | (number & "toFixed") | (number & "toExponential") | (number & "toPrecision") | ("length" & number) | ("charAt" & number) | ("charCodeAt" & number) | ("concat" & number) | ("indexOf" & number) | ("lastIndexOf" & number) | ("localeCompare" & number) | ("match" & number) | ("replace" & number) | ("search" & number) | ("slice" & number) | ("split" & number) | ("substring" & number) | ("toLowerCase" & number) | ("toLocaleLowerCase" & number) | ("toUpperCase" & number) | ("toLocaleUpperCase" & number) | ("trim" & number) | ("substr" & number) >Object : Object type T05 = keyof keyof keyof keyof keyof Object; ->T05 : "toString" | "toLocaleString" | "valueOf" +>T05 : "toString" | "valueOf" | ("toString" & number) | ("toLocaleString" & number) | ("valueOf" & number) | ("toFixed" & number) | ("toExponential" & number) | ("toPrecision" & number) >Object : Object type T06 = keyof keyof keyof keyof keyof keyof Object; ->T06 : number | "length" | "toString" | "valueOf" | "charAt" | "charCodeAt" | "concat" | "indexOf" | "lastIndexOf" | "localeCompare" | "match" | "replace" | "search" | "slice" | "split" | "substring" | "toLowerCase" | "toLocaleLowerCase" | "toUpperCase" | "toLocaleUpperCase" | "trim" | "substr" +>T06 : number | "length" | "toString" | "valueOf" | "charAt" | "charCodeAt" | "concat" | "indexOf" | "lastIndexOf" | "localeCompare" | "match" | "replace" | "search" | "slice" | "split" | "substring" | "toLowerCase" | "toLocaleLowerCase" | "toUpperCase" | "toLocaleUpperCase" | "trim" | "substr" | ("toString" & number) | ("valueOf" & number) | (number & "length") | (number & "toString") | (number & "toLocaleString") | (number & "valueOf") | (number & "charAt") | (number & "charCodeAt") | (number & "concat") | (number & "indexOf") | (number & "lastIndexOf") | (number & "localeCompare") | (number & "match") | (number & "replace") | (number & "search") | (number & "slice") | (number & "split") | (number & "substring") | (number & "toLowerCase") | (number & "toLocaleLowerCase") | (number & "toUpperCase") | (number & "toLocaleUpperCase") | (number & "trim") | (number & "substr") | (number & "toFixed") | (number & "toExponential") | (number & "toPrecision") | ("length" & number) | ("charAt" & number) | ("charCodeAt" & number) | ("concat" & number) | ("indexOf" & number) | ("lastIndexOf" & number) | ("localeCompare" & number) | ("match" & number) | ("replace" & number) | ("search" & number) | ("slice" & number) | ("split" & number) | ("substring" & number) | ("toLowerCase" & number) | ("toLocaleLowerCase" & number) | ("toUpperCase" & number) | ("toLocaleUpperCase" & number) | ("trim" & number) | ("substr" & number) >Object : Object type T10 = Shape["name"]; @@ -242,62 +242,128 @@ function f10(shape: Shape) { >10 : 10 } -function f20(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) { ->f20 : (k1: keyof (T | U), k2: keyof T | keyof U, o1: T | U, o2: T & U) => void +function f20(x: T | U, y: T & U, k1: keyof (T | U), k2: keyof T & keyof U, k3: keyof (T & U), k4: keyof T | keyof U) { +>f20 : (x: T | U, y: T & U, k1: keyof T & keyof U, k2: keyof T & keyof U, k3: keyof T | keyof U, k4: keyof T | keyof U) => void >T : T >U : U ->k1 : keyof (T | U) +>x : T | U >T : T >U : U ->k2 : keyof T | keyof U +>y : T & U >T : T >U : U ->o1 : T | U +>k1 : keyof T & keyof U >T : T >U : U ->o2 : T & U +>k2 : keyof T & keyof U +>T : T +>U : U +>k3 : keyof T | keyof U +>T : T +>U : U +>k4 : keyof T | keyof U >T : T >U : U - o1[k1]; ->o1[k1] : (T | U)[keyof (T | U)] ->o1 : T | U ->k1 : keyof (T | U) - - o1[k2]; // Error ->o1[k2] : (T | U)[keyof T | keyof U] ->o1 : T | U ->k2 : keyof T | keyof U - - o2[k1]; ->o2[k1] : (T & U)[keyof (T | U)] ->o2 : T & U ->k1 : keyof (T | U) - - o2[k2]; ->o2[k2] : (T & U)[keyof T | keyof U] ->o2 : T & U ->k2 : keyof T | keyof U - - o1 = o2; ->o1 = o2 : T & U ->o1 : T | U ->o2 : T & U - - o2 = o1; // Error ->o2 = o1 : T | U ->o2 : T & U ->o1 : T | U - - k1 = k2; // Error ->k1 = k2 : keyof T | keyof U ->k1 : keyof (T | U) ->k2 : keyof T | keyof U + x[k1]; +>x[k1] : (T | U)[keyof T & keyof U] +>x : T | U +>k1 : keyof T & keyof U + + x[k2]; +>x[k2] : (T | U)[keyof T & keyof U] +>x : T | U +>k2 : keyof T & keyof U + + x[k3]; // Error +>x[k3] : (T | U)[keyof T | keyof U] +>x : T | U +>k3 : keyof T | keyof U + + x[k4]; // Error +>x[k4] : (T | U)[keyof T | keyof U] +>x : T | U +>k4 : keyof T | keyof U + + y[k1]; +>y[k1] : (T & U)[keyof T & keyof U] +>y : T & U +>k1 : keyof T & keyof U + + y[k2]; +>y[k2] : (T & U)[keyof T & keyof U] +>y : T & U +>k2 : keyof T & keyof U + + y[k3]; +>y[k3] : (T & U)[keyof T | keyof U] +>y : T & U +>k3 : keyof T | keyof U + + y[k4]; +>y[k4] : (T & U)[keyof T | keyof U] +>y : T & U +>k4 : keyof T | keyof U + + k1 = k2; +>k1 = k2 : keyof T & keyof U +>k1 : keyof T & keyof U +>k2 : keyof T & keyof U + + k1 = k3; // Error +>k1 = k3 : keyof T | keyof U +>k1 : keyof T & keyof U +>k3 : keyof T | keyof U + + k1 = k4; // Error +>k1 = k4 : keyof T | keyof U +>k1 : keyof T & keyof U +>k4 : keyof T | keyof U k2 = k1; ->k2 = k1 : keyof (T | U) ->k2 : keyof T | keyof U ->k1 : keyof (T | U) +>k2 = k1 : keyof T & keyof U +>k2 : keyof T & keyof U +>k1 : keyof T & keyof U + + k2 = k3; // Error +>k2 = k3 : keyof T | keyof U +>k2 : keyof T & keyof U +>k3 : keyof T | keyof U + + k2 = k4; // Error +>k2 = k4 : keyof T | keyof U +>k2 : keyof T & keyof U +>k4 : keyof T | keyof U + + k3 = k1; +>k3 = k1 : keyof T & keyof U +>k3 : keyof T | keyof U +>k1 : keyof T & keyof U + + k3 = k2; +>k3 = k2 : keyof T & keyof U +>k3 : keyof T | keyof U +>k2 : keyof T & keyof U + + k3 = k4; +>k3 = k4 : keyof T | keyof U +>k3 : keyof T | keyof U +>k4 : keyof T | keyof U + + k4 = k1; +>k4 = k1 : keyof T & keyof U +>k4 : keyof T | keyof U +>k1 : keyof T & keyof U + + k4 = k2; +>k4 = k2 : keyof T & keyof U +>k4 : keyof T | keyof U +>k2 : keyof T & keyof U + + k4 = k3; +>k4 = k3 : keyof T | keyof U +>k4 : keyof T | keyof U +>k3 : keyof T | keyof U } // Repro from #17166 diff --git a/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts index e0c1f544d9704..03d4ae01ea1fa 100644 --- a/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts +++ b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts @@ -567,3 +567,21 @@ function f3>(t: T, k: K, tk: T[K]): void { type Predicates = { [T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T] } + +// Repro from #23618 + +type DBBoolTable = { [k in K]: 0 | 1 } +enum Flag { + FLAG_1 = "flag_1", + FLAG_2 = "flag_2" +} + +type SimpleDBRecord = { staticField: number } & DBBoolTable +function getFlagsFromSimpleRecord(record: SimpleDBRecord, flags: Flag[]) { + return record[flags[0]]; +} + +type DynamicDBRecord = ({ dynamicField: number } | { dynamicField: string }) & DBBoolTable +function getFlagsFromDynamicRecord(record: DynamicDBRecord, flags: Flag[]) { + return record[flags[0]]; +} diff --git a/tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts b/tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts index 618f483655e04..bb2b9d951179b 100644 --- a/tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts +++ b/tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts @@ -67,15 +67,32 @@ function f10(shape: Shape) { setProperty(shape, cond ? "name" : "size", 10); // Error } -function f20(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) { - o1[k1]; - o1[k2]; // Error - o2[k1]; - o2[k2]; - o1 = o2; - o2 = o1; // Error - k1 = k2; // Error +function f20(x: T | U, y: T & U, k1: keyof (T | U), k2: keyof T & keyof U, k3: keyof (T & U), k4: keyof T | keyof U) { + x[k1]; + x[k2]; + x[k3]; // Error + x[k4]; // Error + + y[k1]; + y[k2]; + y[k3]; + y[k4]; + + k1 = k2; + k1 = k3; // Error + k1 = k4; // Error + k2 = k1; + k2 = k3; // Error + k2 = k4; // Error + + k3 = k1; + k3 = k2; + k3 = k4; + + k4 = k1; + k4 = k2; + k4 = k3; } // Repro from #17166