Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions tsc/internal/checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ const (
CachedTypeKindDecoratorContextStatic
CachedTypeKindDecoratorContextPrivate
CachedTypeKindDecoratorContextPrivateStatic
CachedTypeKindSimplifiedConditionalTypeForReading
CachedTypeKindSimplifiedConditionalTypeForWriting
)

// CachedTypeKey
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
simplifiedConditionalTypeWritingCache.ts(7,9): error TS2322: Type 'T["a"]' is not assignable to type 'Value<T>'.
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 extends { a: string; b: number }> = T["a" | "b"] extends unknown
? T["a" | "b"]
: never;

function test<T extends { a: string; b: number }>(value: Value<T>, a: T["a"]) {
const read: T["a"] | T["b"] = value;
const write: Value<T> = a;
~~~~~
!!! error TS2322: Type 'T["a"]' is not assignable to type 'Value<T>'.
!!! 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'.
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//// [tests/cases/compiler/simplifiedConditionalTypeWritingCache.ts] ////

//// [simplifiedConditionalTypeWritingCache.ts]
type Value<T extends { a: string; b: number }> = T["a" | "b"] extends unknown
? T["a" | "b"]
: never;

function test<T extends { a: string; b: number }>(value: Value<T>, a: T["a"]) {
const read: T["a"] | T["b"] = value;
const write: Value<T> = a;
}


//// [simplifiedConditionalTypeWritingCache.js]
"use strict";
function test(value, a) {
const read = value;
const write = a;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//// [tests/cases/compiler/simplifiedConditionalTypeWritingCache.ts] ////

=== simplifiedConditionalTypeWritingCache.ts ===
type Value<T extends { a: string; b: number }> = 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<T extends { a: string; b: number }>(value: Value<T>, 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<T> = 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))
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//// [tests/cases/compiler/simplifiedConditionalTypeWritingCache.ts] ////

=== simplifiedConditionalTypeWritingCache.ts ===
type Value<T extends { a: string; b: number }> = T["a" | "b"] extends unknown
>Value : Value<T>
>a : string
>b : number

? T["a" | "b"]
: never;

function test<T extends { a: string; b: number }>(value: Value<T>, a: T["a"]) {
>test : <T extends { a: string; b: number; }>(value: Value<T>, a: T["a"]) => void
>a : string
>b : number
>value : Value<T>
>a : T["a"]

const read: T["a"] | T["b"] = value;
>read : T["a"] | T["b"]
>value : Value<T>

const write: Value<T> = a;
>write : Value<T>
>a : T["a"]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
type Value<T extends { a: string; b: number }> = T["a" | "b"] extends unknown
? T["a" | "b"]
: never;

function test<T extends { a: string; b: number }>(value: Value<T>, a: T["a"]) {
const read: T["a"] | T["b"] = value;
const write: Value<T> = a;
}