diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2ca07e30f287b..fda7332dcccb8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18538,6 +18538,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getPropertyTypeForIndexType(originalObjectType: Type, objectType: Type, indexType: Type, fullIndexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression | undefined, accessFlags: AccessFlags) { + if (indexType.flags & TypeFlags.Substitution) { + indexType = (indexType as SubstitutionType).baseType; + } const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined; const propName = accessNode && isPrivateIdentifier(accessNode) ? undefined : getPropertyNameFromIndex(indexType, accessNode); diff --git a/tests/baselines/reference/nonGenericIndexedAccessInConditionalTrueBranch1.symbols b/tests/baselines/reference/nonGenericIndexedAccessInConditionalTrueBranch1.symbols new file mode 100644 index 0000000000000..b837974d2482f --- /dev/null +++ b/tests/baselines/reference/nonGenericIndexedAccessInConditionalTrueBranch1.symbols @@ -0,0 +1,39 @@ +//// [tests/cases/compiler/nonGenericIndexedAccessInConditionalTrueBranch1.ts] //// + +=== nonGenericIndexedAccessInConditionalTrueBranch1.ts === +// https://github.com/microsoft/TypeScript/issues/57109 + +type A = { +>A : Symbol(A, Decl(nonGenericIndexedAccessInConditionalTrueBranch1.ts, 0, 0)) + + k: symbol; +>k : Symbol(k, Decl(nonGenericIndexedAccessInConditionalTrueBranch1.ts, 2, 10)) + +}; + +type B = "k" extends keyof A ? A["k"] : never; +>B : Symbol(B, Decl(nonGenericIndexedAccessInConditionalTrueBranch1.ts, 4, 2)) +>A : Symbol(A, Decl(nonGenericIndexedAccessInConditionalTrueBranch1.ts, 0, 0)) +>A : Symbol(A, Decl(nonGenericIndexedAccessInConditionalTrueBranch1.ts, 0, 0)) + +type C = { +>C : Symbol(C, Decl(nonGenericIndexedAccessInConditionalTrueBranch1.ts, 6, 46)) + + k: symbol; +>k : Symbol(k, Decl(nonGenericIndexedAccessInConditionalTrueBranch1.ts, 8, 10)) + + other: boolean; +>other : Symbol(other, Decl(nonGenericIndexedAccessInConditionalTrueBranch1.ts, 9, 12)) + +}; + +type D = "k" extends keyof C ? C["k"] : never; +>D : Symbol(D, Decl(nonGenericIndexedAccessInConditionalTrueBranch1.ts, 11, 2)) +>C : Symbol(C, Decl(nonGenericIndexedAccessInConditionalTrueBranch1.ts, 6, 46)) +>C : Symbol(C, Decl(nonGenericIndexedAccessInConditionalTrueBranch1.ts, 6, 46)) + +type E = "k" extends keyof C ? C["k" | "other"] : never; +>E : Symbol(E, Decl(nonGenericIndexedAccessInConditionalTrueBranch1.ts, 13, 46)) +>C : Symbol(C, Decl(nonGenericIndexedAccessInConditionalTrueBranch1.ts, 6, 46)) +>C : Symbol(C, Decl(nonGenericIndexedAccessInConditionalTrueBranch1.ts, 6, 46)) + diff --git a/tests/baselines/reference/nonGenericIndexedAccessInConditionalTrueBranch1.types b/tests/baselines/reference/nonGenericIndexedAccessInConditionalTrueBranch1.types new file mode 100644 index 0000000000000..05f91d30491d7 --- /dev/null +++ b/tests/baselines/reference/nonGenericIndexedAccessInConditionalTrueBranch1.types @@ -0,0 +1,41 @@ +//// [tests/cases/compiler/nonGenericIndexedAccessInConditionalTrueBranch1.ts] //// + +=== nonGenericIndexedAccessInConditionalTrueBranch1.ts === +// https://github.com/microsoft/TypeScript/issues/57109 + +type A = { +>A : A +> : ^ + + k: symbol; +>k : symbol +> : ^^^^^^ + +}; + +type B = "k" extends keyof A ? A["k"] : never; +>B : symbol +> : ^^^^^^ + +type C = { +>C : C +> : ^ + + k: symbol; +>k : symbol +> : ^^^^^^ + + other: boolean; +>other : boolean +> : ^^^^^^^ + +}; + +type D = "k" extends keyof C ? C["k"] : never; +>D : symbol +> : ^^^^^^ + +type E = "k" extends keyof C ? C["k" | "other"] : never; +>E : boolean | symbol +> : ^^^^^^^^^^^^^^^^ + diff --git a/tests/baselines/reference/substitutionTypeUsedAsIndex.symbols b/tests/baselines/reference/substitutionTypeUsedAsIndex.symbols new file mode 100644 index 0000000000000..bf6174ffdfc46 --- /dev/null +++ b/tests/baselines/reference/substitutionTypeUsedAsIndex.symbols @@ -0,0 +1,23 @@ +//// [tests/cases/compiler/substitutionTypeUsedAsIndex.ts] //// + +=== substitutionTypeUsedAsIndex.ts === +// repro from https://github.com/microsoft/TypeScript/issues/54886 + +interface Dict_54886 { +>Dict_54886 : Symbol(Dict_54886, Decl(substitutionTypeUsedAsIndex.ts, 0, 0)) + + foo: 1; +>foo : Symbol(Dict_54886.foo, Decl(substitutionTypeUsedAsIndex.ts, 2, 22)) + + bar: 1; +>bar : Symbol(Dict_54886.bar, Decl(substitutionTypeUsedAsIndex.ts, 3, 9)) +} + +type FF_54886 = "foo" extends "foo" | "bar" ? "foo" : never; +>FF_54886 : Symbol(FF_54886, Decl(substitutionTypeUsedAsIndex.ts, 5, 1)) + +type C_54886 = Dict_54886[FF_54886]; // ok +>C_54886 : Symbol(C_54886, Decl(substitutionTypeUsedAsIndex.ts, 7, 60)) +>Dict_54886 : Symbol(Dict_54886, Decl(substitutionTypeUsedAsIndex.ts, 0, 0)) +>FF_54886 : Symbol(FF_54886, Decl(substitutionTypeUsedAsIndex.ts, 5, 1)) + diff --git a/tests/baselines/reference/substitutionTypeUsedAsIndex.types b/tests/baselines/reference/substitutionTypeUsedAsIndex.types new file mode 100644 index 0000000000000..b05d0e2a54e2a --- /dev/null +++ b/tests/baselines/reference/substitutionTypeUsedAsIndex.types @@ -0,0 +1,23 @@ +//// [tests/cases/compiler/substitutionTypeUsedAsIndex.ts] //// + +=== substitutionTypeUsedAsIndex.ts === +// repro from https://github.com/microsoft/TypeScript/issues/54886 + +interface Dict_54886 { + foo: 1; +>foo : 1 +> : ^ + + bar: 1; +>bar : 1 +> : ^ +} + +type FF_54886 = "foo" extends "foo" | "bar" ? "foo" : never; +>FF_54886 : "foo" +> : ^^^^^ + +type C_54886 = Dict_54886[FF_54886]; // ok +>C_54886 : 1 +> : ^ + diff --git a/tests/cases/compiler/nonGenericIndexedAccessInConditionalTrueBranch1.ts b/tests/cases/compiler/nonGenericIndexedAccessInConditionalTrueBranch1.ts new file mode 100644 index 0000000000000..ccfc45bc093c0 --- /dev/null +++ b/tests/cases/compiler/nonGenericIndexedAccessInConditionalTrueBranch1.ts @@ -0,0 +1,18 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/57109 + +type A = { + k: symbol; +}; + +type B = "k" extends keyof A ? A["k"] : never; + +type C = { + k: symbol; + other: boolean; +}; + +type D = "k" extends keyof C ? C["k"] : never; +type E = "k" extends keyof C ? C["k" | "other"] : never; diff --git a/tests/cases/compiler/substitutionTypeUsedAsIndex.ts b/tests/cases/compiler/substitutionTypeUsedAsIndex.ts new file mode 100644 index 0000000000000..3a880c039cc5d --- /dev/null +++ b/tests/cases/compiler/substitutionTypeUsedAsIndex.ts @@ -0,0 +1,12 @@ +// @strict: true +// @noEmit: true + +// repro from https://github.com/microsoft/TypeScript/issues/54886 + +interface Dict_54886 { + foo: 1; + bar: 1; +} + +type FF_54886 = "foo" extends "foo" | "bar" ? "foo" : never; +type C_54886 = Dict_54886[FF_54886]; // ok