diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 024c3d4a983c3..ccd731e7a2c4d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6037,11 +6037,12 @@ namespace ts { const id = objectType.id + "," + indexType.id; return indexedAccessTypes[id] || (indexedAccessTypes[id] = createIndexedAccessType(objectType, indexType)); } - const apparentType = getApparentType(objectType); - if (indexType.flags & TypeFlags.Union && !(indexType.flags & TypeFlags.Primitive)) { + const apparentObjectType = getApparentType(objectType); + const apparentIndexType = indexType.flags & TypeFlags.Index ? stringOrNumberType : indexType; + if (apparentIndexType.flags & TypeFlags.Union && !(apparentIndexType.flags & TypeFlags.Primitive)) { const propTypes: Type[] = []; - for (const t of (indexType).types) { - const propType = getPropertyTypeForIndexType(apparentType, t, accessNode, /*cacheSymbol*/ false); + for (const t of (apparentIndexType).types) { + const propType = getPropertyTypeForIndexType(apparentObjectType, t, accessNode, /*cacheSymbol*/ false); if (propType === unknownType) { return unknownType; } @@ -6049,7 +6050,7 @@ namespace ts { } return getUnionType(propTypes); } - return getPropertyTypeForIndexType(apparentType, indexType, accessNode, /*cacheSymbol*/ true); + return getPropertyTypeForIndexType(apparentObjectType, apparentIndexType, accessNode, /*cacheSymbol*/ true); } function getTypeFromIndexedAccessTypeNode(node: IndexedAccessTypeNode) { @@ -7123,7 +7124,10 @@ namespace ts { if (source.flags & TypeFlags.Index) { // A keyof T is related to a union type containing both string and number - if (maybeTypeOfKind(target, TypeFlags.String) && maybeTypeOfKind(target, TypeFlags.Number)) { + const related = relation === comparableRelation ? + maybeTypeOfKind(target, TypeFlags.String | TypeFlags.Number) : + maybeTypeOfKind(target, TypeFlags.String) && maybeTypeOfKind(target, TypeFlags.Number); + if (related) { return Ternary.True; } } @@ -14254,7 +14258,7 @@ namespace ts { if (!isTypeAnyOrAllConstituentTypesHaveKind(leftType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) { error(left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol); } - if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.Object | TypeFlags.TypeParameter)) { + if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.Object | TypeFlags.TypeParameter | TypeFlags.IndexedAccess)) { error(right, Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); } return booleanType; @@ -17148,7 +17152,7 @@ namespace ts { const rightType = checkNonNullExpression(node.expression); // unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved // in this case error about missing name is already reported - do not report extra one - if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.Object | TypeFlags.TypeParameter)) { + if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.Object | TypeFlags.TypeParameter | TypeFlags.IndexedAccess)) { error(node.expression, Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter); } diff --git a/tests/baselines/reference/keyofAndIndexedAccess.js b/tests/baselines/reference/keyofAndIndexedAccess.js index dd59a5a1b4c72..eef81f4d5f76d 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.js +++ b/tests/baselines/reference/keyofAndIndexedAccess.js @@ -181,6 +181,46 @@ function f40(c: C) { let z: Z = c["z"]; } +function f50(k: keyof T, s: string, n: number) { + const x1 = s as keyof T; + const x2 = n as keyof T; + const x3 = k as string; + const x4 = k as number; + const x5 = k as string | number; +} + +function f51(k: K, s: string, n: number) { + const x1 = s as keyof T; + const x2 = n as keyof T; + const x3 = k as string; + const x4 = k as number; + const x5 = k as string | number; +} + +function f52(obj: { [x: string]: boolean }, k: keyof T, s: string, n: number) { + const x1 = obj[s]; + const x2 = obj[n]; + const x3 = obj[k]; +} + +function f53(obj: { [x: string]: boolean }, k: K, s: string, n: number) { + const x1 = obj[s]; + const x2 = obj[n]; + const x3 = obj[k]; +} + +function f54(obj: T, key: keyof T) { + for (let s in obj[key]) { + } + const b = "foo" in obj[key]; +} + +function f55(obj: T, key: K) { + for (let s in obj[key]) { + } + const b = "foo" in obj[key]; +} + // Repros from #12011 class Base { @@ -329,6 +369,40 @@ function f40(c) { var y = c["y"]; var z = c["z"]; } +function f50(k, s, n) { + var x1 = s; + var x2 = n; + var x3 = k; + var x4 = k; + var x5 = k; +} +function f51(k, s, n) { + var x1 = s; + var x2 = n; + var x3 = k; + var x4 = k; + var x5 = k; +} +function f52(obj, k, s, n) { + var x1 = obj[s]; + var x2 = obj[n]; + var x3 = obj[k]; +} +function f53(obj, k, s, n) { + var x1 = obj[s]; + var x2 = obj[n]; + var x3 = obj[k]; +} +function f54(obj, key) { + for (var s in obj[key]) { + } + var b = "foo" in obj[key]; +} +function f55(obj, key) { + for (var s in obj[key]) { + } + var b = "foo" in obj[key]; +} // Repros from #12011 var Base = (function () { function Base() { @@ -454,6 +528,16 @@ declare class C { private z; } declare function f40(c: C): void; +declare function f50(k: keyof T, s: string, n: number): void; +declare function f51(k: K, s: string, n: number): void; +declare function f52(obj: { + [x: string]: boolean; +}, k: keyof T, s: string, n: number): void; +declare function f53(obj: { + [x: string]: boolean; +}, k: K, s: string, n: number): void; +declare function f54(obj: T, key: keyof T): void; +declare function f55(obj: T, key: K): void; declare class Base { get(prop: K): this[K]; set(prop: K, value: this[K]): void; diff --git a/tests/baselines/reference/keyofAndIndexedAccess.symbols b/tests/baselines/reference/keyofAndIndexedAccess.symbols index a76cf32b8d2fa..0b10e368821bd 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.symbols +++ b/tests/baselines/reference/keyofAndIndexedAccess.symbols @@ -626,84 +626,242 @@ function f40(c: C) { >"z" : Symbol(C.z, Decl(keyofAndIndexedAccess.ts, 167, 24)) } +function f50(k: keyof T, s: string, n: number) { +>f50 : Symbol(f50, Decl(keyofAndIndexedAccess.ts, 180, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 182, 13)) +>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 182, 16)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 182, 13)) +>s : Symbol(s, Decl(keyofAndIndexedAccess.ts, 182, 27)) +>n : Symbol(n, Decl(keyofAndIndexedAccess.ts, 182, 38)) + + const x1 = s as keyof T; +>x1 : Symbol(x1, Decl(keyofAndIndexedAccess.ts, 183, 9)) +>s : Symbol(s, Decl(keyofAndIndexedAccess.ts, 182, 27)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 182, 13)) + + const x2 = n as keyof T; +>x2 : Symbol(x2, Decl(keyofAndIndexedAccess.ts, 184, 9)) +>n : Symbol(n, Decl(keyofAndIndexedAccess.ts, 182, 38)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 182, 13)) + + const x3 = k as string; +>x3 : Symbol(x3, Decl(keyofAndIndexedAccess.ts, 185, 9)) +>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 182, 16)) + + const x4 = k as number; +>x4 : Symbol(x4, Decl(keyofAndIndexedAccess.ts, 186, 9)) +>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 182, 16)) + + const x5 = k as string | number; +>x5 : Symbol(x5, Decl(keyofAndIndexedAccess.ts, 187, 9)) +>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 182, 16)) +} + +function f51(k: K, s: string, n: number) { +>f51 : Symbol(f51, Decl(keyofAndIndexedAccess.ts, 188, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 190, 13)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 190, 15)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 190, 13)) +>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 190, 35)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 190, 15)) +>s : Symbol(s, Decl(keyofAndIndexedAccess.ts, 190, 40)) +>n : Symbol(n, Decl(keyofAndIndexedAccess.ts, 190, 51)) + + const x1 = s as keyof T; +>x1 : Symbol(x1, Decl(keyofAndIndexedAccess.ts, 191, 9)) +>s : Symbol(s, Decl(keyofAndIndexedAccess.ts, 190, 40)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 190, 13)) + + const x2 = n as keyof T; +>x2 : Symbol(x2, Decl(keyofAndIndexedAccess.ts, 192, 9)) +>n : Symbol(n, Decl(keyofAndIndexedAccess.ts, 190, 51)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 190, 13)) + + const x3 = k as string; +>x3 : Symbol(x3, Decl(keyofAndIndexedAccess.ts, 193, 9)) +>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 190, 35)) + + const x4 = k as number; +>x4 : Symbol(x4, Decl(keyofAndIndexedAccess.ts, 194, 9)) +>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 190, 35)) + + const x5 = k as string | number; +>x5 : Symbol(x5, Decl(keyofAndIndexedAccess.ts, 195, 9)) +>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 190, 35)) +} + +function f52(obj: { [x: string]: boolean }, k: keyof T, s: string, n: number) { +>f52 : Symbol(f52, Decl(keyofAndIndexedAccess.ts, 196, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 198, 13)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 198, 16)) +>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 198, 24)) +>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 198, 46)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 198, 13)) +>s : Symbol(s, Decl(keyofAndIndexedAccess.ts, 198, 58)) +>n : Symbol(n, Decl(keyofAndIndexedAccess.ts, 198, 69)) + + const x1 = obj[s]; +>x1 : Symbol(x1, Decl(keyofAndIndexedAccess.ts, 199, 9)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 198, 16)) +>s : Symbol(s, Decl(keyofAndIndexedAccess.ts, 198, 58)) + + const x2 = obj[n]; +>x2 : Symbol(x2, Decl(keyofAndIndexedAccess.ts, 200, 9)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 198, 16)) +>n : Symbol(n, Decl(keyofAndIndexedAccess.ts, 198, 69)) + + const x3 = obj[k]; +>x3 : Symbol(x3, Decl(keyofAndIndexedAccess.ts, 201, 9)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 198, 16)) +>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 198, 46)) +} + +function f53(obj: { [x: string]: boolean }, k: K, s: string, n: number) { +>f53 : Symbol(f53, Decl(keyofAndIndexedAccess.ts, 202, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 204, 13)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 204, 15)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 204, 13)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 204, 35)) +>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 204, 43)) +>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 204, 65)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 204, 15)) +>s : Symbol(s, Decl(keyofAndIndexedAccess.ts, 204, 71)) +>n : Symbol(n, Decl(keyofAndIndexedAccess.ts, 204, 82)) + + const x1 = obj[s]; +>x1 : Symbol(x1, Decl(keyofAndIndexedAccess.ts, 205, 9)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 204, 35)) +>s : Symbol(s, Decl(keyofAndIndexedAccess.ts, 204, 71)) + + const x2 = obj[n]; +>x2 : Symbol(x2, Decl(keyofAndIndexedAccess.ts, 206, 9)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 204, 35)) +>n : Symbol(n, Decl(keyofAndIndexedAccess.ts, 204, 82)) + + const x3 = obj[k]; +>x3 : Symbol(x3, Decl(keyofAndIndexedAccess.ts, 207, 9)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 204, 35)) +>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 204, 65)) +} + +function f54(obj: T, key: keyof T) { +>f54 : Symbol(f54, Decl(keyofAndIndexedAccess.ts, 208, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 210, 13)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 210, 16)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 210, 13)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 210, 23)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 210, 13)) + + for (let s in obj[key]) { +>s : Symbol(s, Decl(keyofAndIndexedAccess.ts, 211, 12)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 210, 16)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 210, 23)) + } + const b = "foo" in obj[key]; +>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 213, 9)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 210, 16)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 210, 23)) +} + +function f55(obj: T, key: K) { +>f55 : Symbol(f55, Decl(keyofAndIndexedAccess.ts, 214, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 216, 13)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 216, 15)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 216, 13)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 216, 35)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 216, 13)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 216, 42)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 216, 15)) + + for (let s in obj[key]) { +>s : Symbol(s, Decl(keyofAndIndexedAccess.ts, 217, 12)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 216, 35)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 216, 42)) + } + const b = "foo" in obj[key]; +>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 219, 9)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 216, 35)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 216, 42)) +} + // Repros from #12011 class Base { ->Base : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 180, 1)) +>Base : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 220, 1)) get(prop: K) { ->get : Symbol(Base.get, Decl(keyofAndIndexedAccess.ts, 184, 12)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 185, 8)) ->prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 185, 30)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 185, 8)) +>get : Symbol(Base.get, Decl(keyofAndIndexedAccess.ts, 224, 12)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 225, 8)) +>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 225, 30)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 225, 8)) return this[prop]; ->this : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 180, 1)) ->prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 185, 30)) +>this : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 220, 1)) +>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 225, 30)) } set(prop: K, value: this[K]) { ->set : Symbol(Base.set, Decl(keyofAndIndexedAccess.ts, 187, 5)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 188, 8)) ->prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 188, 30)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 188, 8)) ->value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 188, 38)) ->K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 188, 8)) +>set : Symbol(Base.set, Decl(keyofAndIndexedAccess.ts, 227, 5)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 228, 8)) +>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 228, 30)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 228, 8)) +>value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 228, 38)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 228, 8)) this[prop] = value; ->this : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 180, 1)) ->prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 188, 30)) ->value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 188, 38)) +>this : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 220, 1)) +>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 228, 30)) +>value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 228, 38)) } } class Person extends Base { ->Person : Symbol(Person, Decl(keyofAndIndexedAccess.ts, 191, 1)) ->Base : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 180, 1)) +>Person : Symbol(Person, Decl(keyofAndIndexedAccess.ts, 231, 1)) +>Base : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 220, 1)) parts: number; ->parts : Symbol(Person.parts, Decl(keyofAndIndexedAccess.ts, 193, 27)) +>parts : Symbol(Person.parts, Decl(keyofAndIndexedAccess.ts, 233, 27)) constructor(parts: number) { ->parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 195, 16)) +>parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 235, 16)) super(); ->super : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 180, 1)) +>super : Symbol(Base, Decl(keyofAndIndexedAccess.ts, 220, 1)) this.set("parts", parts); ->this.set : Symbol(Base.set, Decl(keyofAndIndexedAccess.ts, 187, 5)) ->this : Symbol(Person, Decl(keyofAndIndexedAccess.ts, 191, 1)) ->set : Symbol(Base.set, Decl(keyofAndIndexedAccess.ts, 187, 5)) ->parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 195, 16)) +>this.set : Symbol(Base.set, Decl(keyofAndIndexedAccess.ts, 227, 5)) +>this : Symbol(Person, Decl(keyofAndIndexedAccess.ts, 231, 1)) +>set : Symbol(Base.set, Decl(keyofAndIndexedAccess.ts, 227, 5)) +>parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 235, 16)) } getParts() { ->getParts : Symbol(Person.getParts, Decl(keyofAndIndexedAccess.ts, 198, 5)) +>getParts : Symbol(Person.getParts, Decl(keyofAndIndexedAccess.ts, 238, 5)) return this.get("parts") ->this.get : Symbol(Base.get, Decl(keyofAndIndexedAccess.ts, 184, 12)) ->this : Symbol(Person, Decl(keyofAndIndexedAccess.ts, 191, 1)) ->get : Symbol(Base.get, Decl(keyofAndIndexedAccess.ts, 184, 12)) +>this.get : Symbol(Base.get, Decl(keyofAndIndexedAccess.ts, 224, 12)) +>this : Symbol(Person, Decl(keyofAndIndexedAccess.ts, 231, 1)) +>get : Symbol(Base.get, Decl(keyofAndIndexedAccess.ts, 224, 12)) } } class OtherPerson { ->OtherPerson : Symbol(OtherPerson, Decl(keyofAndIndexedAccess.ts, 202, 1)) +>OtherPerson : Symbol(OtherPerson, Decl(keyofAndIndexedAccess.ts, 242, 1)) parts: number; ->parts : Symbol(OtherPerson.parts, Decl(keyofAndIndexedAccess.ts, 204, 19)) +>parts : Symbol(OtherPerson.parts, Decl(keyofAndIndexedAccess.ts, 244, 19)) constructor(parts: number) { ->parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 206, 16)) +>parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 246, 16)) setProperty(this, "parts", parts); >setProperty : Symbol(setProperty, Decl(keyofAndIndexedAccess.ts, 79, 1)) ->this : Symbol(OtherPerson, Decl(keyofAndIndexedAccess.ts, 202, 1)) ->parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 206, 16)) +>this : Symbol(OtherPerson, Decl(keyofAndIndexedAccess.ts, 242, 1)) +>parts : Symbol(parts, Decl(keyofAndIndexedAccess.ts, 246, 16)) } getParts() { ->getParts : Symbol(OtherPerson.getParts, Decl(keyofAndIndexedAccess.ts, 208, 5)) +>getParts : Symbol(OtherPerson.getParts, Decl(keyofAndIndexedAccess.ts, 248, 5)) return getProperty(this, "parts") >getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 75, 26)) ->this : Symbol(OtherPerson, Decl(keyofAndIndexedAccess.ts, 202, 1)) +>this : Symbol(OtherPerson, Decl(keyofAndIndexedAccess.ts, 242, 1)) } } diff --git a/tests/baselines/reference/keyofAndIndexedAccess.types b/tests/baselines/reference/keyofAndIndexedAccess.types index c252ea4e2bd97..020ac1141261e 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.types +++ b/tests/baselines/reference/keyofAndIndexedAccess.types @@ -737,6 +737,188 @@ function f40(c: C) { >"z" : "z" } +function f50(k: keyof T, s: string, n: number) { +>f50 : (k: keyof T, s: string, n: number) => void +>T : T +>k : keyof T +>T : T +>s : string +>n : number + + const x1 = s as keyof T; +>x1 : keyof T +>s as keyof T : keyof T +>s : string +>T : T + + const x2 = n as keyof T; +>x2 : keyof T +>n as keyof T : keyof T +>n : number +>T : T + + const x3 = k as string; +>x3 : string +>k as string : string +>k : keyof T + + const x4 = k as number; +>x4 : number +>k as number : number +>k : keyof T + + const x5 = k as string | number; +>x5 : string | number +>k as string | number : string | number +>k : keyof T +} + +function f51(k: K, s: string, n: number) { +>f51 : (k: K, s: string, n: number) => void +>T : T +>K : K +>T : T +>k : K +>K : K +>s : string +>n : number + + const x1 = s as keyof T; +>x1 : keyof T +>s as keyof T : keyof T +>s : string +>T : T + + const x2 = n as keyof T; +>x2 : keyof T +>n as keyof T : keyof T +>n : number +>T : T + + const x3 = k as string; +>x3 : string +>k as string : string +>k : K + + const x4 = k as number; +>x4 : number +>k as number : number +>k : K + + const x5 = k as string | number; +>x5 : string | number +>k as string | number : string | number +>k : K +} + +function f52(obj: { [x: string]: boolean }, k: keyof T, s: string, n: number) { +>f52 : (obj: { [x: string]: boolean; }, k: keyof T, s: string, n: number) => void +>T : T +>obj : { [x: string]: boolean; } +>x : string +>k : keyof T +>T : T +>s : string +>n : number + + const x1 = obj[s]; +>x1 : boolean +>obj[s] : boolean +>obj : { [x: string]: boolean; } +>s : string + + const x2 = obj[n]; +>x2 : boolean +>obj[n] : boolean +>obj : { [x: string]: boolean; } +>n : number + + const x3 = obj[k]; +>x3 : boolean +>obj[k] : boolean +>obj : { [x: string]: boolean; } +>k : keyof T +} + +function f53(obj: { [x: string]: boolean }, k: K, s: string, n: number) { +>f53 : (obj: { [x: string]: boolean; }, k: K, s: string, n: number) => void +>T : T +>K : K +>T : T +>obj : { [x: string]: boolean; } +>x : string +>k : K +>K : K +>s : string +>n : number + + const x1 = obj[s]; +>x1 : boolean +>obj[s] : boolean +>obj : { [x: string]: boolean; } +>s : string + + const x2 = obj[n]; +>x2 : boolean +>obj[n] : boolean +>obj : { [x: string]: boolean; } +>n : number + + const x3 = obj[k]; +>x3 : { [x: string]: boolean; }[K] +>obj[k] : { [x: string]: boolean; }[K] +>obj : { [x: string]: boolean; } +>k : K +} + +function f54(obj: T, key: keyof T) { +>f54 : (obj: T, key: keyof T) => void +>T : T +>obj : T +>T : T +>key : keyof T +>T : T + + for (let s in obj[key]) { +>s : string +>obj[key] : T[keyof T] +>obj : T +>key : keyof T + } + const b = "foo" in obj[key]; +>b : boolean +>"foo" in obj[key] : boolean +>"foo" : "foo" +>obj[key] : T[keyof T] +>obj : T +>key : keyof T +} + +function f55(obj: T, key: K) { +>f55 : (obj: T, key: K) => void +>T : T +>K : K +>T : T +>obj : T +>T : T +>key : K +>K : K + + for (let s in obj[key]) { +>s : string +>obj[key] : T[K] +>obj : T +>key : K + } + const b = "foo" in obj[key]; +>b : boolean +>"foo" in obj[key] : boolean +>"foo" : "foo" +>obj[key] : T[K] +>obj : T +>key : K +} + // Repros from #12011 class Base { diff --git a/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts index 1e874aaf80f8a..522bfe34e156e 100644 --- a/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts +++ b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts @@ -181,6 +181,46 @@ function f40(c: C) { let z: Z = c["z"]; } +function f50(k: keyof T, s: string, n: number) { + const x1 = s as keyof T; + const x2 = n as keyof T; + const x3 = k as string; + const x4 = k as number; + const x5 = k as string | number; +} + +function f51(k: K, s: string, n: number) { + const x1 = s as keyof T; + const x2 = n as keyof T; + const x3 = k as string; + const x4 = k as number; + const x5 = k as string | number; +} + +function f52(obj: { [x: string]: boolean }, k: keyof T, s: string, n: number) { + const x1 = obj[s]; + const x2 = obj[n]; + const x3 = obj[k]; +} + +function f53(obj: { [x: string]: boolean }, k: K, s: string, n: number) { + const x1 = obj[s]; + const x2 = obj[n]; + const x3 = obj[k]; +} + +function f54(obj: T, key: keyof T) { + for (let s in obj[key]) { + } + const b = "foo" in obj[key]; +} + +function f55(obj: T, key: K) { + for (let s in obj[key]) { + } + const b = "foo" in obj[key]; +} + // Repros from #12011 class Base {