diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index 2a4ead5003a89..9842f4f713e0d 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -26809,6 +26809,8 @@ func (c *Checker) getIndexTypeEx(t *Type, indexFlags IndexFlags) *Type { switch { case c.isNoInferType(t): return c.getNoInferType(c.getIndexTypeEx(t.AsSubstitutionType().baseType, indexFlags)) + case t.flags&TypeFlagsSubstitution != 0 && !c.isGenericType(t): + return c.getIndexTypeEx(c.getSubstitutionIntersection(t), indexFlags) case c.shouldDeferIndexType(t, indexFlags): return c.getIndexTypeForGenericType(t, indexFlags) case t.flags&TypeFlagsUnion != 0: diff --git a/tsc/testdata/baselines/reference/compiler/substitutionTypeNonGenericIndexType1.symbols b/tsc/testdata/baselines/reference/compiler/substitutionTypeNonGenericIndexType1.symbols new file mode 100644 index 0000000000000..7ca5986fa6817 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/substitutionTypeNonGenericIndexType1.symbols @@ -0,0 +1,35 @@ +//// [tests/cases/compiler/substitutionTypeNonGenericIndexType1.ts] //// + +=== substitutionTypeNonGenericIndexType1.ts === +// https://github.com/microsoft/TypeScript/issues/61728 + +type BasicConditional = keyof T extends any +>BasicConditional : Symbol(BasicConditional, Decl(substitutionTypeNonGenericIndexType1.ts, 0, 0)) +>T : Symbol(T, Decl(substitutionTypeNonGenericIndexType1.ts, 2, 22)) +>T : Symbol(T, Decl(substitutionTypeNonGenericIndexType1.ts, 2, 22)) + + ? true + : false; + +type Config = { rejectClose: true }; +>Config : Symbol(Config, Decl(substitutionTypeNonGenericIndexType1.ts, 4, 10)) +>rejectClose : Symbol(rejectClose, Decl(substitutionTypeNonGenericIndexType1.ts, 6, 15)) + +type Test = +>Test : Symbol(Test, Decl(substitutionTypeNonGenericIndexType1.ts, 6, 36)) + + Config extends {} +>Config : Symbol(Config, Decl(substitutionTypeNonGenericIndexType1.ts, 4, 10)) + + ? { + rejectClose: BasicConditional; +>rejectClose : Symbol(rejectClose, Decl(substitutionTypeNonGenericIndexType1.ts, 9, 7)) +>BasicConditional : Symbol(BasicConditional, Decl(substitutionTypeNonGenericIndexType1.ts, 0, 0)) +>Config : Symbol(Config, Decl(substitutionTypeNonGenericIndexType1.ts, 4, 10)) + } + : never; + +type RejectClose = Test["rejectClose"]; +>RejectClose : Symbol(RejectClose, Decl(substitutionTypeNonGenericIndexType1.ts, 12, 12)) +>Test : Symbol(Test, Decl(substitutionTypeNonGenericIndexType1.ts, 6, 36)) + diff --git a/tsc/testdata/baselines/reference/compiler/substitutionTypeNonGenericIndexType1.types b/tsc/testdata/baselines/reference/compiler/substitutionTypeNonGenericIndexType1.types new file mode 100644 index 0000000000000..0fdac10b02588 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/substitutionTypeNonGenericIndexType1.types @@ -0,0 +1,32 @@ +//// [tests/cases/compiler/substitutionTypeNonGenericIndexType1.ts] //// + +=== substitutionTypeNonGenericIndexType1.ts === +// https://github.com/microsoft/TypeScript/issues/61728 + +type BasicConditional = keyof T extends any +>BasicConditional : BasicConditional + + ? true +>true : true + + : false; +>false : false + +type Config = { rejectClose: true }; +>Config : Config +>rejectClose : true +>true : true + +type Test = +>Test : { rejectClose: BasicConditional; } + + Config extends {} + ? { + rejectClose: BasicConditional; +>rejectClose : true + } + : never; + +type RejectClose = Test["rejectClose"]; +>RejectClose : true + diff --git a/tsc/testdata/baselines/reference/compiler/substitutionTypeNonGenericIndexType2.symbols b/tsc/testdata/baselines/reference/compiler/substitutionTypeNonGenericIndexType2.symbols new file mode 100644 index 0000000000000..b1801fd76cf52 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/substitutionTypeNonGenericIndexType2.symbols @@ -0,0 +1,30 @@ +//// [tests/cases/compiler/substitutionTypeNonGenericIndexType2.ts] //// + +=== substitutionTypeNonGenericIndexType2.ts === +type BasicConditional = keyof T extends infer R ? R : never; +>BasicConditional : Symbol(BasicConditional, Decl(substitutionTypeNonGenericIndexType2.ts, 0, 0)) +>T : Symbol(T, Decl(substitutionTypeNonGenericIndexType2.ts, 0, 22)) +>T : Symbol(T, Decl(substitutionTypeNonGenericIndexType2.ts, 0, 22)) +>R : Symbol(R, Decl(substitutionTypeNonGenericIndexType2.ts, 0, 48)) +>R : Symbol(R, Decl(substitutionTypeNonGenericIndexType2.ts, 0, 48)) + +type Config = { rejectClose: true }; +>Config : Symbol(Config, Decl(substitutionTypeNonGenericIndexType2.ts, 0, 63)) +>rejectClose : Symbol(rejectClose, Decl(substitutionTypeNonGenericIndexType2.ts, 2, 15)) + +type Test = Config extends {} +>Test : Symbol(Test, Decl(substitutionTypeNonGenericIndexType2.ts, 2, 36)) +>Config : Symbol(Config, Decl(substitutionTypeNonGenericIndexType2.ts, 0, 63)) + + ? { + rejectClose: BasicConditional; +>rejectClose : Symbol(rejectClose, Decl(substitutionTypeNonGenericIndexType2.ts, 5, 5)) +>BasicConditional : Symbol(BasicConditional, Decl(substitutionTypeNonGenericIndexType2.ts, 0, 0)) +>Config : Symbol(Config, Decl(substitutionTypeNonGenericIndexType2.ts, 0, 63)) + } + : never; + +const test: Test["rejectClose"] = "rejectClose"; +>test : Symbol(test, Decl(substitutionTypeNonGenericIndexType2.ts, 10, 5)) +>Test : Symbol(Test, Decl(substitutionTypeNonGenericIndexType2.ts, 2, 36)) + diff --git a/tsc/testdata/baselines/reference/compiler/substitutionTypeNonGenericIndexType2.types b/tsc/testdata/baselines/reference/compiler/substitutionTypeNonGenericIndexType2.types new file mode 100644 index 0000000000000..01591d4aa310b --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/substitutionTypeNonGenericIndexType2.types @@ -0,0 +1,24 @@ +//// [tests/cases/compiler/substitutionTypeNonGenericIndexType2.ts] //// + +=== substitutionTypeNonGenericIndexType2.ts === +type BasicConditional = keyof T extends infer R ? R : never; +>BasicConditional : BasicConditional + +type Config = { rejectClose: true }; +>Config : Config +>rejectClose : true +>true : true + +type Test = Config extends {} +>Test : { rejectClose: BasicConditional; } + + ? { + rejectClose: BasicConditional; +>rejectClose : "rejectClose" + } + : never; + +const test: Test["rejectClose"] = "rejectClose"; +>test : "rejectClose" +>"rejectClose" : "rejectClose" + diff --git a/tsc/testdata/tests/cases/compiler/substitutionTypeNonGenericIndexType1.ts b/tsc/testdata/tests/cases/compiler/substitutionTypeNonGenericIndexType1.ts new file mode 100644 index 0000000000000..bd9a75f23f103 --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/substitutionTypeNonGenericIndexType1.ts @@ -0,0 +1,18 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/61728 + +type BasicConditional = keyof T extends any + ? true + : false; + +type Config = { rejectClose: true }; +type Test = + Config extends {} + ? { + rejectClose: BasicConditional; + } + : never; + +type RejectClose = Test["rejectClose"]; diff --git a/tsc/testdata/tests/cases/compiler/substitutionTypeNonGenericIndexType2.ts b/tsc/testdata/tests/cases/compiler/substitutionTypeNonGenericIndexType2.ts new file mode 100644 index 0000000000000..fdc159e353c3f --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/substitutionTypeNonGenericIndexType2.ts @@ -0,0 +1,14 @@ +// @strict: true +// @noEmit: true + +type BasicConditional = keyof T extends infer R ? R : never; + +type Config = { rejectClose: true }; + +type Test = Config extends {} + ? { + rejectClose: BasicConditional; + } + : never; + +const test: Test["rejectClose"] = "rejectClose";