diff --git a/tests/baselines/reference/distributiveConditionalTypeConstraints.errors.txt b/tests/baselines/reference/distributiveConditionalTypeConstraints.errors.txt new file mode 100644 index 0000000000000..2b455f4e2eebd --- /dev/null +++ b/tests/baselines/reference/distributiveConditionalTypeConstraints.errors.txt @@ -0,0 +1,108 @@ +distributiveConditionalTypeConstraints.ts(4,9): error TS2322: Type 'boolean' is not assignable to type 'true'. +distributiveConditionalTypeConstraints.ts(5,9): error TS2322: Type 'boolean' is not assignable to type 'false'. +distributiveConditionalTypeConstraints.ts(10,9): error TS2322: Type 'IsArray' is not assignable to type 'false'. + Type 'true' is not assignable to type 'false'. +distributiveConditionalTypeConstraints.ts(15,9): error TS2322: Type 'IsArray' is not assignable to type 'false'. + Type 'true' is not assignable to type 'false'. +distributiveConditionalTypeConstraints.ts(19,9): error TS2322: Type 'IsArray' is not assignable to type 'true'. + Type 'false' is not assignable to type 'true'. + + +==== distributiveConditionalTypeConstraints.ts (5 errors) ==== + type IsArray = T extends unknown[] ? true : false; + + function f1(x: IsArray) { + let t: true = x; // Error + ~ +!!! error TS2322: Type 'boolean' is not assignable to type 'true'. + let f: false = x; // Error + ~ +!!! error TS2322: Type 'boolean' is not assignable to type 'false'. + } + + function f2(x: IsArray) { + let t: true = x; + let f: false = x; // Error + ~ +!!! error TS2322: Type 'IsArray' is not assignable to type 'false'. +!!! error TS2322: Type 'true' is not assignable to type 'false'. + } + + function f3(x: IsArray) { + let t: true = x; + let f: false = x; // Error + ~ +!!! error TS2322: Type 'IsArray' is not assignable to type 'false'. +!!! error TS2322: Type 'true' is not assignable to type 'false'. + } + + function f4(x: IsArray) { + let t: true = x; // Error + ~ +!!! error TS2322: Type 'IsArray' is not assignable to type 'true'. +!!! error TS2322: Type 'false' is not assignable to type 'true'. + let f: false = x; + } + + type ZeroOf = + T extends null ? null : + T extends undefined ? undefined : + T extends string ? "" : + T extends number ? 0 : + T extends boolean ? false : + never; + + function f10(x: ZeroOf) { + let t: "" | 0 | false = x; + } + + // Modified repro from #30152 + + interface A { foo(): void; } + interface B { bar(): void; } + interface C { foo(): void, bar(): void } + + function test1(y: T extends B ? number : string) { + if (typeof y == 'string') { + y; // T extends B ? number : string + } + else { + y; // never + } + const newY: string | number = y; + newY; // string + } + + function test2(y: T extends B ? string : number) { + if (typeof y == 'string') { + y; // never + } + else { + y; // T extends B ? string : number + } + const newY: string | number = y; + newY; // number + } + + function test3(y: T extends C ? number : string) { + if (typeof y == 'string') { + y; // (T extends C ? number : string) & string + } + else { + y; // T extends C ? number : string + } + const newY: string | number = y; + newY; // string | number + } + + function test4(y: T extends C ? string : number) { + if (typeof y == 'string') { + y; // (T extends C ? string : number) & string + } + else { + y; // T extends C ? string : number + } + const newY: string | number = y; + newY; // string | number + } + \ No newline at end of file diff --git a/tests/baselines/reference/distributiveConditionalTypeConstraints.symbols b/tests/baselines/reference/distributiveConditionalTypeConstraints.symbols new file mode 100644 index 0000000000000..762237abde362 --- /dev/null +++ b/tests/baselines/reference/distributiveConditionalTypeConstraints.symbols @@ -0,0 +1,225 @@ +//// [tests/cases/compiler/distributiveConditionalTypeConstraints.ts] //// + +=== distributiveConditionalTypeConstraints.ts === +type IsArray = T extends unknown[] ? true : false; +>IsArray : Symbol(IsArray, Decl(distributiveConditionalTypeConstraints.ts, 0, 0)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 0, 13)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 0, 13)) + +function f1(x: IsArray) { +>f1 : Symbol(f1, Decl(distributiveConditionalTypeConstraints.ts, 0, 53)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 2, 12)) +>x : Symbol(x, Decl(distributiveConditionalTypeConstraints.ts, 2, 30)) +>IsArray : Symbol(IsArray, Decl(distributiveConditionalTypeConstraints.ts, 0, 0)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 2, 12)) + + let t: true = x; // Error +>t : Symbol(t, Decl(distributiveConditionalTypeConstraints.ts, 3, 7)) +>x : Symbol(x, Decl(distributiveConditionalTypeConstraints.ts, 2, 30)) + + let f: false = x; // Error +>f : Symbol(f, Decl(distributiveConditionalTypeConstraints.ts, 4, 7)) +>x : Symbol(x, Decl(distributiveConditionalTypeConstraints.ts, 2, 30)) +} + +function f2(x: IsArray) { +>f2 : Symbol(f2, Decl(distributiveConditionalTypeConstraints.ts, 5, 1)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 7, 12)) +>x : Symbol(x, Decl(distributiveConditionalTypeConstraints.ts, 7, 33)) +>IsArray : Symbol(IsArray, Decl(distributiveConditionalTypeConstraints.ts, 0, 0)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 7, 12)) + + let t: true = x; +>t : Symbol(t, Decl(distributiveConditionalTypeConstraints.ts, 8, 7)) +>x : Symbol(x, Decl(distributiveConditionalTypeConstraints.ts, 7, 33)) + + let f: false = x; // Error +>f : Symbol(f, Decl(distributiveConditionalTypeConstraints.ts, 9, 7)) +>x : Symbol(x, Decl(distributiveConditionalTypeConstraints.ts, 7, 33)) +} + +function f3(x: IsArray) { +>f3 : Symbol(f3, Decl(distributiveConditionalTypeConstraints.ts, 10, 1)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 12, 12)) +>x : Symbol(x, Decl(distributiveConditionalTypeConstraints.ts, 12, 32)) +>IsArray : Symbol(IsArray, Decl(distributiveConditionalTypeConstraints.ts, 0, 0)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 12, 12)) + + let t: true = x; +>t : Symbol(t, Decl(distributiveConditionalTypeConstraints.ts, 13, 7)) +>x : Symbol(x, Decl(distributiveConditionalTypeConstraints.ts, 12, 32)) + + let f: false = x; // Error +>f : Symbol(f, Decl(distributiveConditionalTypeConstraints.ts, 14, 7)) +>x : Symbol(x, Decl(distributiveConditionalTypeConstraints.ts, 12, 32)) +} + +function f4(x: IsArray) { +>f4 : Symbol(f4, Decl(distributiveConditionalTypeConstraints.ts, 15, 1)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 17, 12)) +>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(distributiveConditionalTypeConstraints.ts, 17, 32)) +>IsArray : Symbol(IsArray, Decl(distributiveConditionalTypeConstraints.ts, 0, 0)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 17, 12)) + + let t: true = x; // Error +>t : Symbol(t, Decl(distributiveConditionalTypeConstraints.ts, 18, 7)) +>x : Symbol(x, Decl(distributiveConditionalTypeConstraints.ts, 17, 32)) + + let f: false = x; +>f : Symbol(f, Decl(distributiveConditionalTypeConstraints.ts, 19, 7)) +>x : Symbol(x, Decl(distributiveConditionalTypeConstraints.ts, 17, 32)) +} + +type ZeroOf = +>ZeroOf : Symbol(ZeroOf, Decl(distributiveConditionalTypeConstraints.ts, 20, 1)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 22, 12)) + + T extends null ? null : +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 22, 12)) + + T extends undefined ? undefined : +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 22, 12)) + + T extends string ? "" : +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 22, 12)) + + T extends number ? 0 : +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 22, 12)) + + T extends boolean ? false : +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 22, 12)) + + never; + +function f10(x: ZeroOf) { +>f10 : Symbol(f10, Decl(distributiveConditionalTypeConstraints.ts, 28, 10)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 30, 13)) +>x : Symbol(x, Decl(distributiveConditionalTypeConstraints.ts, 30, 27)) +>ZeroOf : Symbol(ZeroOf, Decl(distributiveConditionalTypeConstraints.ts, 20, 1)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 30, 13)) + + let t: "" | 0 | false = x; +>t : Symbol(t, Decl(distributiveConditionalTypeConstraints.ts, 31, 7)) +>x : Symbol(x, Decl(distributiveConditionalTypeConstraints.ts, 30, 27)) +} + +// Modified repro from #30152 + +interface A { foo(): void; } +>A : Symbol(A, Decl(distributiveConditionalTypeConstraints.ts, 32, 1)) +>foo : Symbol(A.foo, Decl(distributiveConditionalTypeConstraints.ts, 36, 13)) + +interface B { bar(): void; } +>B : Symbol(B, Decl(distributiveConditionalTypeConstraints.ts, 36, 28)) +>bar : Symbol(B.bar, Decl(distributiveConditionalTypeConstraints.ts, 37, 13)) + +interface C { foo(): void, bar(): void } +>C : Symbol(C, Decl(distributiveConditionalTypeConstraints.ts, 37, 28)) +>foo : Symbol(C.foo, Decl(distributiveConditionalTypeConstraints.ts, 38, 13)) +>bar : Symbol(C.bar, Decl(distributiveConditionalTypeConstraints.ts, 38, 26)) + +function test1(y: T extends B ? number : string) { +>test1 : Symbol(test1, Decl(distributiveConditionalTypeConstraints.ts, 38, 40)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 40, 15)) +>A : Symbol(A, Decl(distributiveConditionalTypeConstraints.ts, 32, 1)) +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 40, 28)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 40, 15)) +>B : Symbol(B, Decl(distributiveConditionalTypeConstraints.ts, 36, 28)) + + if (typeof y == 'string') { +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 40, 28)) + + y; // T extends B ? number : string +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 40, 28)) + } + else { + y; // never +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 40, 28)) + } + const newY: string | number = y; +>newY : Symbol(newY, Decl(distributiveConditionalTypeConstraints.ts, 47, 9)) +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 40, 28)) + + newY; // string +>newY : Symbol(newY, Decl(distributiveConditionalTypeConstraints.ts, 47, 9)) +} + +function test2(y: T extends B ? string : number) { +>test2 : Symbol(test2, Decl(distributiveConditionalTypeConstraints.ts, 49, 1)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 51, 15)) +>A : Symbol(A, Decl(distributiveConditionalTypeConstraints.ts, 32, 1)) +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 51, 28)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 51, 15)) +>B : Symbol(B, Decl(distributiveConditionalTypeConstraints.ts, 36, 28)) + + if (typeof y == 'string') { +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 51, 28)) + + y; // never +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 51, 28)) + } + else { + y; // T extends B ? string : number +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 51, 28)) + } + const newY: string | number = y; +>newY : Symbol(newY, Decl(distributiveConditionalTypeConstraints.ts, 58, 9)) +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 51, 28)) + + newY; // number +>newY : Symbol(newY, Decl(distributiveConditionalTypeConstraints.ts, 58, 9)) +} + +function test3(y: T extends C ? number : string) { +>test3 : Symbol(test3, Decl(distributiveConditionalTypeConstraints.ts, 60, 1)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 62, 15)) +>A : Symbol(A, Decl(distributiveConditionalTypeConstraints.ts, 32, 1)) +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 62, 28)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 62, 15)) +>C : Symbol(C, Decl(distributiveConditionalTypeConstraints.ts, 37, 28)) + + if (typeof y == 'string') { +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 62, 28)) + + y; // (T extends C ? number : string) & string +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 62, 28)) + } + else { + y; // T extends C ? number : string +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 62, 28)) + } + const newY: string | number = y; +>newY : Symbol(newY, Decl(distributiveConditionalTypeConstraints.ts, 69, 9)) +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 62, 28)) + + newY; // string | number +>newY : Symbol(newY, Decl(distributiveConditionalTypeConstraints.ts, 69, 9)) +} + +function test4(y: T extends C ? string : number) { +>test4 : Symbol(test4, Decl(distributiveConditionalTypeConstraints.ts, 71, 1)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 73, 15)) +>A : Symbol(A, Decl(distributiveConditionalTypeConstraints.ts, 32, 1)) +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 73, 28)) +>T : Symbol(T, Decl(distributiveConditionalTypeConstraints.ts, 73, 15)) +>C : Symbol(C, Decl(distributiveConditionalTypeConstraints.ts, 37, 28)) + + if (typeof y == 'string') { +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 73, 28)) + + y; // (T extends C ? string : number) & string +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 73, 28)) + } + else { + y; // T extends C ? string : number +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 73, 28)) + } + const newY: string | number = y; +>newY : Symbol(newY, Decl(distributiveConditionalTypeConstraints.ts, 80, 9)) +>y : Symbol(y, Decl(distributiveConditionalTypeConstraints.ts, 73, 28)) + + newY; // string | number +>newY : Symbol(newY, Decl(distributiveConditionalTypeConstraints.ts, 80, 9)) +} + diff --git a/tests/baselines/reference/distributiveConditionalTypeConstraints.types b/tests/baselines/reference/distributiveConditionalTypeConstraints.types new file mode 100644 index 0000000000000..8793a421c9782 --- /dev/null +++ b/tests/baselines/reference/distributiveConditionalTypeConstraints.types @@ -0,0 +1,202 @@ +//// [tests/cases/compiler/distributiveConditionalTypeConstraints.ts] //// + +=== distributiveConditionalTypeConstraints.ts === +type IsArray = T extends unknown[] ? true : false; +>IsArray : IsArray +>true : true +>false : false + +function f1(x: IsArray) { +>f1 : (x: IsArray) => void +>x : IsArray + + let t: true = x; // Error +>t : true +>true : true +>x : boolean + + let f: false = x; // Error +>f : false +>false : false +>x : boolean +} + +function f2(x: IsArray) { +>f2 : (x: IsArray) => void +>x : IsArray + + let t: true = x; +>t : true +>true : true +>x : IsArray + + let f: false = x; // Error +>f : false +>false : false +>x : IsArray +} + +function f3(x: IsArray) { +>f3 : (x: IsArray) => void +>x : IsArray + + let t: true = x; +>t : true +>true : true +>x : IsArray + + let f: false = x; // Error +>f : false +>false : false +>x : IsArray +} + +function f4(x: IsArray) { +>f4 : (x: IsArray) => void +>x : IsArray + + let t: true = x; // Error +>t : true +>true : true +>x : IsArray + + let f: false = x; +>f : false +>false : false +>x : IsArray +} + +type ZeroOf = +>ZeroOf : ZeroOf + + T extends null ? null : + T extends undefined ? undefined : + T extends string ? "" : + T extends number ? 0 : + T extends boolean ? false : +>false : false + + never; + +function f10(x: ZeroOf) { +>f10 : (x: ZeroOf) => void +>x : ZeroOf + + let t: "" | 0 | false = x; +>t : false | "" | 0 +>false : false +>x : false | "" | 0 +} + +// Modified repro from #30152 + +interface A { foo(): void; } +>foo : () => void + +interface B { bar(): void; } +>bar : () => void + +interface C { foo(): void, bar(): void } +>foo : () => void +>bar : () => void + +function test1(y: T extends B ? number : string) { +>test1 : (y: T extends B ? number : string) => void +>y : T extends B ? number : string + + if (typeof y == 'string') { +>typeof y == 'string' : boolean +>typeof y : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>y : T extends B ? number : string +>'string' : "string" + + y; // T extends B ? number : string +>y : T extends B ? number : string + } + else { + y; // never +>y : never + } + const newY: string | number = y; +>newY : string | number +>y : T extends B ? number : string + + newY; // string +>newY : string +} + +function test2(y: T extends B ? string : number) { +>test2 : (y: T extends B ? string : number) => void +>y : T extends B ? string : number + + if (typeof y == 'string') { +>typeof y == 'string' : boolean +>typeof y : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>y : T extends B ? string : number +>'string' : "string" + + y; // never +>y : never + } + else { + y; // T extends B ? string : number +>y : T extends B ? string : number + } + const newY: string | number = y; +>newY : string | number +>y : T extends B ? string : number + + newY; // number +>newY : number +} + +function test3(y: T extends C ? number : string) { +>test3 : (y: T extends C ? number : string) => void +>y : T extends C ? number : string + + if (typeof y == 'string') { +>typeof y == 'string' : boolean +>typeof y : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>y : T extends C ? number : string +>'string' : "string" + + y; // (T extends C ? number : string) & string +>y : (T extends C ? number : string) & string + } + else { + y; // T extends C ? number : string +>y : T extends C ? number : string + } + const newY: string | number = y; +>newY : string | number +>y : string | number + + newY; // string | number +>newY : string | number +} + +function test4(y: T extends C ? string : number) { +>test4 : (y: T extends C ? string : number) => void +>y : T extends C ? string : number + + if (typeof y == 'string') { +>typeof y == 'string' : boolean +>typeof y : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>y : T extends C ? string : number +>'string' : "string" + + y; // (T extends C ? string : number) & string +>y : (T extends C ? string : number) & string + } + else { + y; // T extends C ? string : number +>y : T extends C ? string : number + } + const newY: string | number = y; +>newY : string | number +>y : string | number + + newY; // string | number +>newY : string | number +} + diff --git a/tests/cases/compiler/distributiveConditionalTypeConstraints.ts b/tests/cases/compiler/distributiveConditionalTypeConstraints.ts new file mode 100644 index 0000000000000..82366a73c59ef --- /dev/null +++ b/tests/cases/compiler/distributiveConditionalTypeConstraints.ts @@ -0,0 +1,86 @@ +// @strict: true +// @noEmit: true + +type IsArray = T extends unknown[] ? true : false; + +function f1(x: IsArray) { + let t: true = x; // Error + let f: false = x; // Error +} + +function f2(x: IsArray) { + let t: true = x; + let f: false = x; // Error +} + +function f3(x: IsArray) { + let t: true = x; + let f: false = x; // Error +} + +function f4(x: IsArray) { + let t: true = x; // Error + let f: false = x; +} + +type ZeroOf = + T extends null ? null : + T extends undefined ? undefined : + T extends string ? "" : + T extends number ? 0 : + T extends boolean ? false : + never; + +function f10(x: ZeroOf) { + let t: "" | 0 | false = x; +} + +// Modified repro from #30152 + +interface A { foo(): void; } +interface B { bar(): void; } +interface C { foo(): void, bar(): void } + +function test1(y: T extends B ? number : string) { + if (typeof y == 'string') { + y; // T extends B ? number : string + } + else { + y; // never + } + const newY: string | number = y; + newY; // string +} + +function test2(y: T extends B ? string : number) { + if (typeof y == 'string') { + y; // never + } + else { + y; // T extends B ? string : number + } + const newY: string | number = y; + newY; // number +} + +function test3(y: T extends C ? number : string) { + if (typeof y == 'string') { + y; // (T extends C ? number : string) & string + } + else { + y; // T extends C ? number : string + } + const newY: string | number = y; + newY; // string | number +} + +function test4(y: T extends C ? string : number) { + if (typeof y == 'string') { + y; // (T extends C ? string : number) & string + } + else { + y; // T extends C ? string : number + } + const newY: string | number = y; + newY; // string | number +}