diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index 9b52a55d92310..5419f32d3846d 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -139,6 +139,8 @@ const ( CachedTypeKindDecoratorContextStatic CachedTypeKindDecoratorContextPrivate CachedTypeKindDecoratorContextPrivateStatic + CachedTypeKindSimplifiedConditionalTypeForReading + CachedTypeKindSimplifiedConditionalTypeForWriting ) // CachedTypeKey @@ -28507,6 +28509,16 @@ func (c *Checker) distributeIndexOverObjectType(objectType *Type, indexType *Typ } func (c *Checker) getSimplifiedConditionalType(t *Type, writing bool) *Type { + key := CachedTypeKey{kind: core.IfElse(writing, CachedTypeKindSimplifiedConditionalTypeForWriting, CachedTypeKindSimplifiedConditionalTypeForReading), typeId: t.id} + if cached, ok := c.cachedTypes[key]; ok { + return cached + } + result := c.getSimplifiedConditionalTypeWorker(t, writing) + c.cachedTypes[key] = result + return result +} + +func (c *Checker) getSimplifiedConditionalTypeWorker(t *Type, writing bool) *Type { checkType := t.AsConditionalType().checkType extendsType := t.AsConditionalType().extendsType trueType := c.getTrueTypeFromConditionalType(t) diff --git a/tsc/testdata/baselines/reference/compiler/simplifiedConditionalTypeWritingCache.errors.txt b/tsc/testdata/baselines/reference/compiler/simplifiedConditionalTypeWritingCache.errors.txt new file mode 100644 index 0000000000000..9ed906581b180 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/simplifiedConditionalTypeWritingCache.errors.txt @@ -0,0 +1,21 @@ +simplifiedConditionalTypeWritingCache.ts(7,9): error TS2322: Type 'T["a"]' is not assignable to type 'Value'. + Type 'string' is not assignable to type 'T["a"] & T["b"]'. + Type 'string' is not assignable to type 'T["b"]'. + 'T["b"]' could be instantiated with an arbitrary type which could be unrelated to 'string'. + + +==== simplifiedConditionalTypeWritingCache.ts (1 errors) ==== + type Value = T["a" | "b"] extends unknown + ? T["a" | "b"] + : never; + + function test(value: Value, a: T["a"]) { + const read: T["a"] | T["b"] = value; + const write: Value = a; + ~~~~~ +!!! error TS2322: Type 'T["a"]' is not assignable to type 'Value'. +!!! error TS2322: Type 'string' is not assignable to type 'T["a"] & T["b"]'. +!!! error TS2322: Type 'string' is not assignable to type 'T["b"]'. +!!! error TS2322: 'T["b"]' could be instantiated with an arbitrary type which could be unrelated to 'string'. + } + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/simplifiedConditionalTypeWritingCache.js b/tsc/testdata/baselines/reference/compiler/simplifiedConditionalTypeWritingCache.js new file mode 100644 index 0000000000000..b69d342f0a6cd --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/simplifiedConditionalTypeWritingCache.js @@ -0,0 +1,19 @@ +//// [tests/cases/compiler/simplifiedConditionalTypeWritingCache.ts] //// + +//// [simplifiedConditionalTypeWritingCache.ts] +type Value = T["a" | "b"] extends unknown + ? T["a" | "b"] + : never; + +function test(value: Value, a: T["a"]) { + const read: T["a"] | T["b"] = value; + const write: Value = a; +} + + +//// [simplifiedConditionalTypeWritingCache.js] +"use strict"; +function test(value, a) { + const read = value; + const write = a; +} diff --git a/tsc/testdata/baselines/reference/compiler/simplifiedConditionalTypeWritingCache.symbols b/tsc/testdata/baselines/reference/compiler/simplifiedConditionalTypeWritingCache.symbols new file mode 100644 index 0000000000000..cc30f57fa2753 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/simplifiedConditionalTypeWritingCache.symbols @@ -0,0 +1,39 @@ +//// [tests/cases/compiler/simplifiedConditionalTypeWritingCache.ts] //// + +=== simplifiedConditionalTypeWritingCache.ts === +type Value = T["a" | "b"] extends unknown +>Value : Symbol(Value, Decl(simplifiedConditionalTypeWritingCache.ts, 0, 0)) +>T : Symbol(T, Decl(simplifiedConditionalTypeWritingCache.ts, 0, 11)) +>a : Symbol(a, Decl(simplifiedConditionalTypeWritingCache.ts, 0, 22)) +>b : Symbol(b, Decl(simplifiedConditionalTypeWritingCache.ts, 0, 33)) +>T : Symbol(T, Decl(simplifiedConditionalTypeWritingCache.ts, 0, 11)) + + ? T["a" | "b"] +>T : Symbol(T, Decl(simplifiedConditionalTypeWritingCache.ts, 0, 11)) + + : never; + +function test(value: Value, a: T["a"]) { +>test : Symbol(test, Decl(simplifiedConditionalTypeWritingCache.ts, 2, 10)) +>T : Symbol(T, Decl(simplifiedConditionalTypeWritingCache.ts, 4, 14)) +>a : Symbol(a, Decl(simplifiedConditionalTypeWritingCache.ts, 4, 25)) +>b : Symbol(b, Decl(simplifiedConditionalTypeWritingCache.ts, 4, 36)) +>value : Symbol(value, Decl(simplifiedConditionalTypeWritingCache.ts, 4, 50)) +>Value : Symbol(Value, Decl(simplifiedConditionalTypeWritingCache.ts, 0, 0)) +>T : Symbol(T, Decl(simplifiedConditionalTypeWritingCache.ts, 4, 14)) +>a : Symbol(a, Decl(simplifiedConditionalTypeWritingCache.ts, 4, 66)) +>T : Symbol(T, Decl(simplifiedConditionalTypeWritingCache.ts, 4, 14)) + + const read: T["a"] | T["b"] = value; +>read : Symbol(read, Decl(simplifiedConditionalTypeWritingCache.ts, 5, 7)) +>T : Symbol(T, Decl(simplifiedConditionalTypeWritingCache.ts, 4, 14)) +>T : Symbol(T, Decl(simplifiedConditionalTypeWritingCache.ts, 4, 14)) +>value : Symbol(value, Decl(simplifiedConditionalTypeWritingCache.ts, 4, 50)) + + const write: Value = a; +>write : Symbol(write, Decl(simplifiedConditionalTypeWritingCache.ts, 6, 7)) +>Value : Symbol(Value, Decl(simplifiedConditionalTypeWritingCache.ts, 0, 0)) +>T : Symbol(T, Decl(simplifiedConditionalTypeWritingCache.ts, 4, 14)) +>a : Symbol(a, Decl(simplifiedConditionalTypeWritingCache.ts, 4, 66)) +} + diff --git a/tsc/testdata/baselines/reference/compiler/simplifiedConditionalTypeWritingCache.types b/tsc/testdata/baselines/reference/compiler/simplifiedConditionalTypeWritingCache.types new file mode 100644 index 0000000000000..8e77eb17868ec --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/simplifiedConditionalTypeWritingCache.types @@ -0,0 +1,27 @@ +//// [tests/cases/compiler/simplifiedConditionalTypeWritingCache.ts] //// + +=== simplifiedConditionalTypeWritingCache.ts === +type Value = T["a" | "b"] extends unknown +>Value : Value +>a : string +>b : number + + ? T["a" | "b"] + : never; + +function test(value: Value, a: T["a"]) { +>test : (value: Value, a: T["a"]) => void +>a : string +>b : number +>value : Value +>a : T["a"] + + const read: T["a"] | T["b"] = value; +>read : T["a"] | T["b"] +>value : Value + + const write: Value = a; +>write : Value +>a : T["a"] +} + diff --git a/tsc/testdata/tests/cases/compiler/simplifiedConditionalTypeWritingCache.ts b/tsc/testdata/tests/cases/compiler/simplifiedConditionalTypeWritingCache.ts new file mode 100644 index 0000000000000..457405a3b05d9 --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/simplifiedConditionalTypeWritingCache.ts @@ -0,0 +1,8 @@ +type Value = T["a" | "b"] extends unknown + ? T["a" | "b"] + : never; + +function test(value: Value, a: T["a"]) { + const read: T["a"] | T["b"] = value; + const write: Value = a; +}