Accepting new baselines

This commit is contained in:
Anders Hejlsberg
2016-03-26 08:21:43 -07:00
parent 0820249e71
commit 5a5d89a71e
25 changed files with 1193 additions and 1329 deletions
@@ -1,10 +1,13 @@
tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(5,5): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(31,12): error TS2352: Neither type 'SomeOther' nor type 'SomeBase' is assignable to the other.
tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(31,12): error TS2352: Neither type 'SomeOther' nor type 'SomeBase' is assignable to the other.
Property 'p' is missing in type 'SomeOther'.
tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(35,15): error TS2352: Neither type 'SomeOther' nor type 'SomeDerived' is assignable to the other.
tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(35,15): error TS2352: Neither type 'SomeOther' nor type 'SomeDerived' is assignable to the other.
Property 'x' is missing in type 'SomeOther'.
tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(37,13): error TS2352: Neither type 'SomeDerived' nor type 'SomeOther' is assignable to the other.
Property 'q' is missing in type 'SomeDerived'.
tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(38,13): error TS2352: Neither type 'SomeBase' nor type 'SomeOther' is assignable to the other.
tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(38,13): error TS2352: Neither type 'SomeBase' nor type 'SomeOther' is assignable to the other.
Property 'q' is missing in type 'SomeBase'.
tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(44,5): error TS2304: Cannot find name 'numOrStr'.
@@ -23,7 +26,7 @@ tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(48,44): err
tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(48,50): error TS1005: ';' expected.
==== tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts (18 errors) ====
==== tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts (21 errors) ====
// Function call whose argument is a 1 arg generic function call with explicit type arguments
function fn1<T>(t: T) { }
function fn2(t: any) { }
@@ -58,6 +61,8 @@ tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(48,50): err
someBase = <SomeBase>someBase;
someBase = <SomeBase>someOther; // Error
~~~~~~~~~~~~~~~~~~~
!!! error TS2352: Neither type 'SomeOther' nor type 'SomeBase' is assignable to the other.
~~~~~~~~~~~~~~~~~~~
!!! error TS2352: Neither type 'SomeOther' nor type 'SomeBase' is assignable to the other.
!!! error TS2352: Property 'p' is missing in type 'SomeOther'.
@@ -65,6 +70,8 @@ tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(48,50): err
someDerived = <SomeDerived>someBase;
someDerived = <SomeDerived>someOther; // Error
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2352: Neither type 'SomeOther' nor type 'SomeDerived' is assignable to the other.
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2352: Neither type 'SomeOther' nor type 'SomeDerived' is assignable to the other.
!!! error TS2352: Property 'x' is missing in type 'SomeOther'.
@@ -74,6 +81,8 @@ tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(48,50): err
!!! error TS2352: Property 'q' is missing in type 'SomeDerived'.
someOther = <SomeOther>someBase; // Error
~~~~~~~~~~~~~~~~~~~
!!! error TS2352: Neither type 'SomeBase' nor type 'SomeOther' is assignable to the other.
~~~~~~~~~~~~~~~~~~~
!!! error TS2352: Neither type 'SomeBase' nor type 'SomeOther' is assignable to the other.
!!! error TS2352: Property 'q' is missing in type 'SomeBase'.
someOther = <SomeOther>someOther;
@@ -12,43 +12,37 @@ function foo(x: number | string) {
: x++; // number
}
function foo2(x: number | string) {
// x is assigned in the if true branch, the type is not narrowed
return typeof x === "string"
? (x = 10 && x)// string | number
: x; // string | number
? ((x = "hello") && x) // string
: x; // number
}
function foo3(x: number | string) {
// x is assigned in the if false branch, the type is not narrowed
// even though assigned using same type as narrowed expression
return typeof x === "string"
? (x = "Hello" && x) // string | number
: x; // string | number
? ((x = 10) && x) // number
: x; // number
}
function foo4(x: number | string) {
// false branch updates the variable - so here it is not number
// even though assigned using same type as narrowed expression
return typeof x === "string"
? x // string | number
: (x = 10 && x); // string | number
? x // string
: ((x = 10) && x); // number
}
function foo5(x: number | string) {
// false branch updates the variable - so here it is not number
return typeof x === "string"
? x // string | number
: (x = "hello" && x); // string | number
? x // string
: ((x = "hello") && x); // string
}
function foo6(x: number | string) {
// Modify in both branches
return typeof x === "string"
? (x = 10 && x) // string | number
: (x = "hello" && x); // string | number
? ((x = 10) && x) // number
: ((x = "hello") && x); // string
}
function foo7(x: number | string | boolean) {
return typeof x === "string"
? x === "hello" // string
? x === "hello" // boolean
: typeof x === "boolean"
? x // boolean
: x == 10; // number
: x == 10; // boolean
}
function foo8(x: number | string | boolean) {
var b: number | boolean;
@@ -57,14 +51,14 @@ function foo8(x: number | string | boolean) {
: ((b = x) && // number | boolean
(typeof x === "boolean"
? x // boolean
: x == 10)); // number
: x == 10)); // boolean
}
function foo9(x: number | string) {
var y = 10;
// usage of x or assignment to separate variable shouldn't cause narrowing of type to stop
return typeof x === "string"
? ((y = x.length) && x === "hello") // string
: x === 10; // number
? ((y = x.length) && x === "hello") // boolean
: x === 10; // boolean
}
function foo10(x: number | string | boolean) {
// Mixing typeguards
@@ -77,22 +71,20 @@ function foo10(x: number | string | boolean) {
}
function foo11(x: number | string | boolean) {
// Mixing typeguards
// Assigning value to x deep inside another guard stops narrowing of type too
var b: number | boolean | string;
return typeof x === "string"
? x // number | boolean | string - changed in the false branch
: ((b = x) // x is number | boolean | string - because the assignment changed it
? x // string
: ((b = x) // x is number | boolean
&& typeof x === "number"
&& (x = 10) // assignment to x
&& x); // x is number | boolean | string
&& x); // x is number
}
function foo12(x: number | string | boolean) {
// Mixing typeguards
// Assigning value to x in outer guard shouldn't stop narrowing in the inner expression
var b: number | boolean | string;
return typeof x === "string"
? (x = 10 && x.toString().length) // number | boolean | string - changed here
: ((b = x) // x is number | boolean | string - changed in true branch
? ((x = 10) && x.toString().length) // number
: ((b = x) // x is number | boolean
&& typeof x === "number"
&& x); // x is number
}
@@ -110,43 +102,37 @@ function foo(x) {
: x++; // number
}
function foo2(x) {
// x is assigned in the if true branch, the type is not narrowed
return typeof x === "string"
? (x = 10 && x) // string | number
: x; // string | number
? ((x = "hello") && x) // string
: x; // number
}
function foo3(x) {
// x is assigned in the if false branch, the type is not narrowed
// even though assigned using same type as narrowed expression
return typeof x === "string"
? (x = "Hello" && x) // string | number
: x; // string | number
? ((x = 10) && x) // number
: x; // number
}
function foo4(x) {
// false branch updates the variable - so here it is not number
// even though assigned using same type as narrowed expression
return typeof x === "string"
? x // string | number
: (x = 10 && x); // string | number
? x // string
: ((x = 10) && x); // number
}
function foo5(x) {
// false branch updates the variable - so here it is not number
return typeof x === "string"
? x // string | number
: (x = "hello" && x); // string | number
? x // string
: ((x = "hello") && x); // string
}
function foo6(x) {
// Modify in both branches
return typeof x === "string"
? (x = 10 && x) // string | number
: (x = "hello" && x); // string | number
? ((x = 10) && x) // number
: ((x = "hello") && x); // string
}
function foo7(x) {
return typeof x === "string"
? x === "hello" // string
? x === "hello" // boolean
: typeof x === "boolean"
? x // boolean
: x == 10; // number
: x == 10; // boolean
}
function foo8(x) {
var b;
@@ -155,14 +141,14 @@ function foo8(x) {
: ((b = x) &&
(typeof x === "boolean"
? x // boolean
: x == 10)); // number
: x == 10)); // boolean
}
function foo9(x) {
var y = 10;
// usage of x or assignment to separate variable shouldn't cause narrowing of type to stop
return typeof x === "string"
? ((y = x.length) && x === "hello") // string
: x === 10; // number
? ((y = x.length) && x === "hello") // boolean
: x === 10; // boolean
}
function foo10(x) {
// Mixing typeguards
@@ -175,22 +161,20 @@ function foo10(x) {
}
function foo11(x) {
// Mixing typeguards
// Assigning value to x deep inside another guard stops narrowing of type too
var b;
return typeof x === "string"
? x // number | boolean | string - changed in the false branch
: ((b = x) // x is number | boolean | string - because the assignment changed it
? x // string
: ((b = x) // x is number | boolean
&& typeof x === "number"
&& (x = 10) // assignment to x
&& x); // x is number | boolean | string
&& x); // x is number
}
function foo12(x) {
// Mixing typeguards
// Assigning value to x in outer guard shouldn't stop narrowing in the inner expression
var b;
return typeof x === "string"
? (x = 10 && x.toString().length) // number | boolean | string - changed here
: ((b = x) // x is number | boolean | string - changed in true branch
? ((x = 10) && x.toString().length) // number
: ((b = x) // x is number | boolean
&& typeof x === "number"
&& x); // x is number
}
@@ -25,227 +25,219 @@ function foo2(x: number | string) {
>foo2 : Symbol(foo2, Decl(typeGuardsInConditionalExpression.ts, 11, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 12, 14))
// x is assigned in the if true branch, the type is not narrowed
return typeof x === "string"
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 12, 14))
? (x = 10 && x)// string | number
? ((x = "hello") && x) // string
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 12, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 12, 14))
: x; // string | number
: x; // number
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 12, 14))
}
function foo3(x: number | string) {
>foo3 : Symbol(foo3, Decl(typeGuardsInConditionalExpression.ts, 17, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 18, 14))
>foo3 : Symbol(foo3, Decl(typeGuardsInConditionalExpression.ts, 16, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 17, 14))
// x is assigned in the if false branch, the type is not narrowed
// even though assigned using same type as narrowed expression
return typeof x === "string"
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 18, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 17, 14))
? (x = "Hello" && x) // string | number
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 18, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 18, 14))
? ((x = 10) && x) // number
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 17, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 17, 14))
: x; // string | number
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 18, 14))
: x; // number
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 17, 14))
}
function foo4(x: number | string) {
>foo4 : Symbol(foo4, Decl(typeGuardsInConditionalExpression.ts, 24, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 25, 14))
>foo4 : Symbol(foo4, Decl(typeGuardsInConditionalExpression.ts, 21, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 22, 14))
// false branch updates the variable - so here it is not number
// even though assigned using same type as narrowed expression
return typeof x === "string"
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 25, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 22, 14))
? x // string | number
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 25, 14))
? x // string
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 22, 14))
: (x = 10 && x); // string | number
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 25, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 25, 14))
: ((x = 10) && x); // number
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 22, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 22, 14))
}
function foo5(x: number | string) {
>foo5 : Symbol(foo5, Decl(typeGuardsInConditionalExpression.ts, 31, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14))
>foo5 : Symbol(foo5, Decl(typeGuardsInConditionalExpression.ts, 26, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 27, 14))
// false branch updates the variable - so here it is not number
return typeof x === "string"
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 27, 14))
? x // string | number
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14))
? x // string
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 27, 14))
: (x = "hello" && x); // string | number
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14))
: ((x = "hello") && x); // string
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 27, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 27, 14))
}
function foo6(x: number | string) {
>foo6 : Symbol(foo6, Decl(typeGuardsInConditionalExpression.ts, 37, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14))
>foo6 : Symbol(foo6, Decl(typeGuardsInConditionalExpression.ts, 31, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14))
// Modify in both branches
return typeof x === "string"
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14))
? (x = 10 && x) // string | number
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14))
? ((x = 10) && x) // number
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14))
: (x = "hello" && x); // string | number
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14))
: ((x = "hello") && x); // string
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14))
}
function foo7(x: number | string | boolean) {
>foo7 : Symbol(foo7, Decl(typeGuardsInConditionalExpression.ts, 43, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 44, 14))
>foo7 : Symbol(foo7, Decl(typeGuardsInConditionalExpression.ts, 37, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14))
return typeof x === "string"
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 44, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14))
? x === "hello" // string
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 44, 14))
? x === "hello" // boolean
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14))
: typeof x === "boolean"
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 44, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14))
? x // boolean
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 44, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14))
: x == 10; // number
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 44, 14))
: x == 10; // boolean
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14))
}
function foo8(x: number | string | boolean) {
>foo8 : Symbol(foo8, Decl(typeGuardsInConditionalExpression.ts, 50, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14))
>foo8 : Symbol(foo8, Decl(typeGuardsInConditionalExpression.ts, 44, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 45, 14))
var b: number | boolean;
>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 52, 7))
>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 46, 7))
return typeof x === "string"
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 45, 14))
? x === "hello"
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 45, 14))
: ((b = x) && // number | boolean
>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 52, 7))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14))
>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 46, 7))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 45, 14))
(typeof x === "boolean"
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 45, 14))
? x // boolean
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 45, 14))
: x == 10)); // number
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14))
: x == 10)); // boolean
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 45, 14))
}
function foo9(x: number | string) {
>foo9 : Symbol(foo9, Decl(typeGuardsInConditionalExpression.ts, 59, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 60, 14))
>foo9 : Symbol(foo9, Decl(typeGuardsInConditionalExpression.ts, 53, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 54, 14))
var y = 10;
>y : Symbol(y, Decl(typeGuardsInConditionalExpression.ts, 61, 7))
>y : Symbol(y, Decl(typeGuardsInConditionalExpression.ts, 55, 7))
// usage of x or assignment to separate variable shouldn't cause narrowing of type to stop
return typeof x === "string"
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 60, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 54, 14))
? ((y = x.length) && x === "hello") // string
>y : Symbol(y, Decl(typeGuardsInConditionalExpression.ts, 61, 7))
? ((y = x.length) && x === "hello") // boolean
>y : Symbol(y, Decl(typeGuardsInConditionalExpression.ts, 55, 7))
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 60, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 54, 14))
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 60, 14))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 54, 14))
: x === 10; // number
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 60, 14))
: x === 10; // boolean
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 54, 14))
}
function foo10(x: number | string | boolean) {
>foo10 : Symbol(foo10, Decl(typeGuardsInConditionalExpression.ts, 66, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 67, 15))
>foo10 : Symbol(foo10, Decl(typeGuardsInConditionalExpression.ts, 60, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 61, 15))
// Mixing typeguards
var b: boolean | number;
>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 69, 7))
>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 63, 7))
return typeof x === "string"
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 67, 15))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 61, 15))
? x // string
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 67, 15))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 61, 15))
: ((b = x) // x is number | boolean
>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 69, 7))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 67, 15))
>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 63, 7))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 61, 15))
&& typeof x === "number"
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 67, 15))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 61, 15))
&& x.toString()); // x is number
>x.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 67, 15))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 61, 15))
>toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
}
function foo11(x: number | string | boolean) {
>foo11 : Symbol(foo11, Decl(typeGuardsInConditionalExpression.ts, 75, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15))
>foo11 : Symbol(foo11, Decl(typeGuardsInConditionalExpression.ts, 69, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 70, 15))
// Mixing typeguards
// Assigning value to x deep inside another guard stops narrowing of type too
var b: number | boolean | string;
>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 79, 7))
>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 72, 7))
return typeof x === "string"
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 70, 15))
? x // number | boolean | string - changed in the false branch
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15))
? x // string
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 70, 15))
: ((b = x) // x is number | boolean | string - because the assignment changed it
>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 79, 7))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15))
: ((b = x) // x is number | boolean
>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 72, 7))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 70, 15))
&& typeof x === "number"
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 70, 15))
&& (x = 10) // assignment to x
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15))
&& x); // x is number | boolean | string
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15))
}
function foo12(x: number | string | boolean) {
>foo12 : Symbol(foo12, Decl(typeGuardsInConditionalExpression.ts, 86, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15))
// Mixing typeguards
// Assigning value to x in outer guard shouldn't stop narrowing in the inner expression
var b: number | boolean | string;
>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 90, 7))
return typeof x === "string"
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15))
? (x = 10 && x.toString().length) // number | boolean | string - changed here
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15))
>x.toString().length : Symbol(String.length, Decl(lib.d.ts, --, --))
>x.toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15))
>toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
: ((b = x) // x is number | boolean | string - changed in true branch
>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 90, 7))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15))
&& typeof x === "number"
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 70, 15))
&& x); // x is number
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 70, 15))
}
function foo12(x: number | string | boolean) {
>foo12 : Symbol(foo12, Decl(typeGuardsInConditionalExpression.ts, 79, 1))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 80, 15))
// Mixing typeguards
var b: number | boolean | string;
>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 82, 7))
return typeof x === "string"
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 80, 15))
? ((x = 10) && x.toString().length) // number
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 80, 15))
>x.toString().length : Symbol(String.length, Decl(lib.d.ts, --, --))
>x.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 80, 15))
>toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
: ((b = x) // x is number | boolean
>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 82, 7))
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 80, 15))
&& typeof x === "number"
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 80, 15))
&& x); // x is number
>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 80, 15))
}
@@ -27,98 +27,96 @@ function foo(x: number | string) {
>x : number
}
function foo2(x: number | string) {
>foo2 : (x: number | string) => number | string
>foo2 : (x: number | string) => string | number
>x : number | string
// x is assigned in the if true branch, the type is not narrowed
return typeof x === "string"
>typeof x === "string" ? (x = 10 && x)// string | number : x : number | string
>typeof x === "string" ? ((x = "hello") && x) // string : x : string | number
>typeof x === "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
? (x = 10 && x)// string | number
>(x = 10 && x) : number | string
>x = 10 && x : number | string
>x : number | string
>10 && x : number | string
>10 : number
? ((x = "hello") && x) // string
>((x = "hello") && x) : string
>(x = "hello") && x : string
>(x = "hello") : string
>x = "hello" : string
>x : number | string
>"hello" : string
>x : string
: x; // string | number
>x : number | string
: x; // number
>x : number
}
function foo3(x: number | string) {
>foo3 : (x: number | string) => number | string
>foo3 : (x: number | string) => number
>x : number | string
// x is assigned in the if false branch, the type is not narrowed
// even though assigned using same type as narrowed expression
return typeof x === "string"
>typeof x === "string" ? (x = "Hello" && x) // string | number : x : number | string
>typeof x === "string" ? ((x = 10) && x) // number : x : number
>typeof x === "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
? (x = "Hello" && x) // string | number
>(x = "Hello" && x) : number | string
>x = "Hello" && x : number | string
>x : number | string
>"Hello" && x : number | string
>"Hello" : string
? ((x = 10) && x) // number
>((x = 10) && x) : number
>(x = 10) && x : number
>(x = 10) : number
>x = 10 : number
>x : number | string
>10 : number
>x : number
: x; // string | number
>x : number | string
: x; // number
>x : number
}
function foo4(x: number | string) {
>foo4 : (x: number | string) => number | string
>foo4 : (x: number | string) => string | number
>x : number | string
// false branch updates the variable - so here it is not number
// even though assigned using same type as narrowed expression
return typeof x === "string"
>typeof x === "string" ? x // string | number : (x = 10 && x) : number | string
>typeof x === "string" ? x // string : ((x = 10) && x) : string | number
>typeof x === "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
? x // string | number
>x : number | string
? x // string
>x : string
: (x = 10 && x); // string | number
>(x = 10 && x) : number | string
>x = 10 && x : number | string
: ((x = 10) && x); // number
>((x = 10) && x) : number
>(x = 10) && x : number
>(x = 10) : number
>x = 10 : number
>x : number | string
>10 && x : number | string
>10 : number
>x : number | string
>x : number
}
function foo5(x: number | string) {
>foo5 : (x: number | string) => number | string
>foo5 : (x: number | string) => string
>x : number | string
// false branch updates the variable - so here it is not number
return typeof x === "string"
>typeof x === "string" ? x // string | number : (x = "hello" && x) : number | string
>typeof x === "string" ? x // string : ((x = "hello") && x) : string
>typeof x === "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
? x // string | number
>x : number | string
? x // string
>x : string
: (x = "hello" && x); // string | number
>(x = "hello" && x) : number | string
>x = "hello" && x : number | string
: ((x = "hello") && x); // string
>((x = "hello") && x) : string
>(x = "hello") && x : string
>(x = "hello") : string
>x = "hello" : string
>x : number | string
>"hello" && x : number | string
>"hello" : string
>x : number | string
>x : string
}
function foo6(x: number | string) {
>foo6 : (x: number | string) => number | string
@@ -126,40 +124,42 @@ function foo6(x: number | string) {
// Modify in both branches
return typeof x === "string"
>typeof x === "string" ? (x = 10 && x) // string | number : (x = "hello" && x) : number | string
>typeof x === "string" ? ((x = 10) && x) // number : ((x = "hello") && x) : number | string
>typeof x === "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
? (x = 10 && x) // string | number
>(x = 10 && x) : number | string
>x = 10 && x : number | string
? ((x = 10) && x) // number
>((x = 10) && x) : number
>(x = 10) && x : number
>(x = 10) : number
>x = 10 : number
>x : number | string
>10 && x : number | string
>10 : number
>x : number | string
>x : number
: (x = "hello" && x); // string | number
>(x = "hello" && x) : number | string
>x = "hello" && x : number | string
: ((x = "hello") && x); // string
>((x = "hello") && x) : string
>(x = "hello") && x : string
>(x = "hello") : string
>x = "hello" : string
>x : number | string
>"hello" && x : number | string
>"hello" : string
>x : number | string
>x : string
}
function foo7(x: number | string | boolean) {
>foo7 : (x: number | string | boolean) => boolean
>x : number | string | boolean
return typeof x === "string"
>typeof x === "string" ? x === "hello" // string : typeof x === "boolean" ? x // boolean : x == 10 : boolean
>typeof x === "string" ? x === "hello" // boolean : typeof x === "boolean" ? x // boolean : x == 10 : boolean
>typeof x === "string" : boolean
>typeof x : string
>x : number | string | boolean
>"string" : string
? x === "hello" // string
? x === "hello" // boolean
>x === "hello" : boolean
>x : string
>"hello" : string
@@ -174,7 +174,7 @@ function foo7(x: number | string | boolean) {
? x // boolean
>x : boolean
: x == 10; // number
: x == 10; // boolean
>x == 10 : boolean
>x : number
>10 : number
@@ -217,7 +217,7 @@ function foo8(x: number | string | boolean) {
? x // boolean
>x : boolean
: x == 10)); // number
: x == 10)); // boolean
>x == 10 : boolean
>x : number
>10 : number
@@ -232,13 +232,13 @@ function foo9(x: number | string) {
// usage of x or assignment to separate variable shouldn't cause narrowing of type to stop
return typeof x === "string"
>typeof x === "string" ? ((y = x.length) && x === "hello") // string : x === 10 : boolean
>typeof x === "string" ? ((y = x.length) && x === "hello") // boolean : x === 10 : boolean
>typeof x === "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
? ((y = x.length) && x === "hello") // string
? ((y = x.length) && x === "hello") // boolean
>((y = x.length) && x === "hello") : boolean
>(y = x.length) && x === "hello" : boolean
>(y = x.length) : number
@@ -251,7 +251,7 @@ function foo9(x: number | string) {
>x : string
>"hello" : string
: x === 10; // number
: x === 10; // boolean
>x === 10 : boolean
>x : number
>10 : number
@@ -296,38 +296,37 @@ function foo10(x: number | string | boolean) {
>toString : (radix?: number) => string
}
function foo11(x: number | string | boolean) {
>foo11 : (x: number | string | boolean) => number | string | boolean
>foo11 : (x: number | string | boolean) => string | number
>x : number | string | boolean
// Mixing typeguards
// Assigning value to x deep inside another guard stops narrowing of type too
var b: number | boolean | string;
>b : number | boolean | string
return typeof x === "string"
>typeof x === "string" ? x // number | boolean | string - changed in the false branch : ((b = x) // x is number | boolean | string - because the assignment changed it && typeof x === "number" && (x = 10) // assignment to x && x) : number | string | boolean
>typeof x === "string" ? x // string : ((b = x) // x is number | boolean && typeof x === "number" && (x = 10) // assignment to x && x) : string | number
>typeof x === "string" : boolean
>typeof x : string
>x : number | string | boolean
>"string" : string
? x // number | boolean | string - changed in the false branch
>x : number | string | boolean
? x // string
>x : string
: ((b = x) // x is number | boolean | string - because the assignment changed it
>((b = x) // x is number | boolean | string - because the assignment changed it && typeof x === "number" && (x = 10) // assignment to x && x) : number | string | boolean
>(b = x) // x is number | boolean | string - because the assignment changed it && typeof x === "number" && (x = 10) // assignment to x && x : number | string | boolean
>(b = x) // x is number | boolean | string - because the assignment changed it && typeof x === "number" && (x = 10) : number
>(b = x) // x is number | boolean | string - because the assignment changed it && typeof x === "number" : boolean
>(b = x) : number | string | boolean
>b = x : number | string | boolean
: ((b = x) // x is number | boolean
>((b = x) // x is number | boolean && typeof x === "number" && (x = 10) // assignment to x && x) : number
>(b = x) // x is number | boolean && typeof x === "number" && (x = 10) // assignment to x && x : number
>(b = x) // x is number | boolean && typeof x === "number" && (x = 10) : number
>(b = x) // x is number | boolean && typeof x === "number" : boolean
>(b = x) : number | boolean
>b = x : number | boolean
>b : number | boolean | string
>x : number | string | boolean
>x : number | boolean
&& typeof x === "number"
>typeof x === "number" : boolean
>typeof x : string
>x : number | string | boolean
>x : number | boolean
>"number" : string
&& (x = 10) // assignment to x
@@ -336,51 +335,51 @@ function foo11(x: number | string | boolean) {
>x : number | string | boolean
>10 : number
&& x); // x is number | boolean | string
>x : number | string | boolean
&& x); // x is number
>x : number
}
function foo12(x: number | string | boolean) {
>foo12 : (x: number | string | boolean) => number
>x : number | string | boolean
// Mixing typeguards
// Assigning value to x in outer guard shouldn't stop narrowing in the inner expression
var b: number | boolean | string;
>b : number | boolean | string
return typeof x === "string"
>typeof x === "string" ? (x = 10 && x.toString().length) // number | boolean | string - changed here : ((b = x) // x is number | boolean | string - changed in true branch && typeof x === "number" && x) : number
>typeof x === "string" ? ((x = 10) && x.toString().length) // number : ((b = x) // x is number | boolean && typeof x === "number" && x) : number
>typeof x === "string" : boolean
>typeof x : string
>x : number | string | boolean
>"string" : string
? (x = 10 && x.toString().length) // number | boolean | string - changed here
>(x = 10 && x.toString().length) : number
>x = 10 && x.toString().length : number
? ((x = 10) && x.toString().length) // number
>((x = 10) && x.toString().length) : number
>(x = 10) && x.toString().length : number
>(x = 10) : number
>x = 10 : number
>x : number | string | boolean
>10 && x.toString().length : number
>10 : number
>x.toString().length : number
>x.toString() : string
>x.toString : (radix?: number) => string
>x : number | string | boolean
>x : number
>toString : (radix?: number) => string
>length : number
: ((b = x) // x is number | boolean | string - changed in true branch
>((b = x) // x is number | boolean | string - changed in true branch && typeof x === "number" && x) : number
>(b = x) // x is number | boolean | string - changed in true branch && typeof x === "number" && x : number
>(b = x) // x is number | boolean | string - changed in true branch && typeof x === "number" : boolean
>(b = x) : number | string | boolean
>b = x : number | string | boolean
: ((b = x) // x is number | boolean
>((b = x) // x is number | boolean && typeof x === "number" && x) : number
>(b = x) // x is number | boolean && typeof x === "number" && x : number
>(b = x) // x is number | boolean && typeof x === "number" : boolean
>(b = x) : number | boolean
>b = x : number | boolean
>b : number | boolean | string
>x : number | string | boolean
>x : number | boolean
&& typeof x === "number"
>typeof x === "number" : boolean
>typeof x : string
>x : number | string | boolean
>x : number | boolean
>"number" : string
&& x); // x is number
@@ -0,0 +1,60 @@
//// [typeGuardsInDoStatement.ts]
let cond: boolean;
function a(x: string | number | boolean) {
x = true;
do {
x; // boolean | string
x = undefined;
} while (typeof x === "string")
x; // number | boolean
}
function b(x: string | number | boolean) {
x = true;
do {
x; // boolean | string
if (cond) continue;
x = undefined;
} while (typeof x === "string")
x; // number | boolean
}
function c(x: string | number) {
x = "";
do {
x; // string
if (cond) break;
x = undefined;
} while (typeof x === "string")
x; // string | number
}
//// [typeGuardsInDoStatement.js]
var cond;
function a(x) {
x = true;
do {
x; // boolean | string
x = undefined;
} while (typeof x === "string");
x; // number | boolean
}
function b(x) {
x = true;
do {
x; // boolean | string
if (cond)
continue;
x = undefined;
} while (typeof x === "string");
x; // number | boolean
}
function c(x) {
x = "";
do {
x; // string
if (cond)
break;
x = undefined;
} while (typeof x === "string");
x; // string | number
}
@@ -0,0 +1,74 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInDoStatement.ts ===
let cond: boolean;
>cond : Symbol(cond, Decl(typeGuardsInDoStatement.ts, 0, 3))
function a(x: string | number | boolean) {
>a : Symbol(a, Decl(typeGuardsInDoStatement.ts, 0, 18))
>x : Symbol(x, Decl(typeGuardsInDoStatement.ts, 1, 11))
x = true;
>x : Symbol(x, Decl(typeGuardsInDoStatement.ts, 1, 11))
do {
x; // boolean | string
>x : Symbol(x, Decl(typeGuardsInDoStatement.ts, 1, 11))
x = undefined;
>x : Symbol(x, Decl(typeGuardsInDoStatement.ts, 1, 11))
>undefined : Symbol(undefined)
} while (typeof x === "string")
>x : Symbol(x, Decl(typeGuardsInDoStatement.ts, 1, 11))
x; // number | boolean
>x : Symbol(x, Decl(typeGuardsInDoStatement.ts, 1, 11))
}
function b(x: string | number | boolean) {
>b : Symbol(b, Decl(typeGuardsInDoStatement.ts, 8, 1))
>x : Symbol(x, Decl(typeGuardsInDoStatement.ts, 9, 11))
x = true;
>x : Symbol(x, Decl(typeGuardsInDoStatement.ts, 9, 11))
do {
x; // boolean | string
>x : Symbol(x, Decl(typeGuardsInDoStatement.ts, 9, 11))
if (cond) continue;
>cond : Symbol(cond, Decl(typeGuardsInDoStatement.ts, 0, 3))
x = undefined;
>x : Symbol(x, Decl(typeGuardsInDoStatement.ts, 9, 11))
>undefined : Symbol(undefined)
} while (typeof x === "string")
>x : Symbol(x, Decl(typeGuardsInDoStatement.ts, 9, 11))
x; // number | boolean
>x : Symbol(x, Decl(typeGuardsInDoStatement.ts, 9, 11))
}
function c(x: string | number) {
>c : Symbol(c, Decl(typeGuardsInDoStatement.ts, 17, 1))
>x : Symbol(x, Decl(typeGuardsInDoStatement.ts, 18, 11))
x = "";
>x : Symbol(x, Decl(typeGuardsInDoStatement.ts, 18, 11))
do {
x; // string
>x : Symbol(x, Decl(typeGuardsInDoStatement.ts, 18, 11))
if (cond) break;
>cond : Symbol(cond, Decl(typeGuardsInDoStatement.ts, 0, 3))
x = undefined;
>x : Symbol(x, Decl(typeGuardsInDoStatement.ts, 18, 11))
>undefined : Symbol(undefined)
} while (typeof x === "string")
>x : Symbol(x, Decl(typeGuardsInDoStatement.ts, 18, 11))
x; // string | number
>x : Symbol(x, Decl(typeGuardsInDoStatement.ts, 18, 11))
}
@@ -0,0 +1,92 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInDoStatement.ts ===
let cond: boolean;
>cond : boolean
function a(x: string | number | boolean) {
>a : (x: string | number | boolean) => void
>x : string | number | boolean
x = true;
>x = true : boolean
>x : string | number | boolean
>true : boolean
do {
x; // boolean | string
>x : boolean | string
x = undefined;
>x = undefined : undefined
>x : string | number | boolean
>undefined : undefined
} while (typeof x === "string")
>typeof x === "string" : boolean
>typeof x : string
>x : string | number | boolean
>"string" : string
x; // number | boolean
>x : number | boolean
}
function b(x: string | number | boolean) {
>b : (x: string | number | boolean) => void
>x : string | number | boolean
x = true;
>x = true : boolean
>x : string | number | boolean
>true : boolean
do {
x; // boolean | string
>x : boolean | string
if (cond) continue;
>cond : boolean
x = undefined;
>x = undefined : undefined
>x : string | number | boolean
>undefined : undefined
} while (typeof x === "string")
>typeof x === "string" : boolean
>typeof x : string
>x : string | number | boolean
>"string" : string
x; // number | boolean
>x : number | boolean
}
function c(x: string | number) {
>c : (x: string | number) => void
>x : string | number
x = "";
>x = "" : string
>x : string | number
>"" : string
do {
x; // string
>x : string
if (cond) break;
>cond : boolean
x = undefined;
>x = undefined : undefined
>x : string | number
>undefined : undefined
} while (typeof x === "string")
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
>"string" : string
x; // string | number
>x : string | number
}
@@ -0,0 +1,48 @@
//// [typeGuardsInForStatement.ts]
let cond: boolean;
function a(x: string | number) {
for (x = undefined; typeof x !== "number"; x = undefined) {
x; // string
}
x; // number
}
function b(x: string | number) {
for (x = undefined; typeof x !== "number"; x = undefined) {
x; // string
if (cond) continue;
}
x; // number
}
function c(x: string | number) {
for (x = undefined; typeof x !== "number"; x = undefined) {
x; // string
if (cond) break;
}
x; // string | number
}
//// [typeGuardsInForStatement.js]
var cond;
function a(x) {
for (x = undefined; typeof x !== "number"; x = undefined) {
x; // string
}
x; // number
}
function b(x) {
for (x = undefined; typeof x !== "number"; x = undefined) {
x; // string
if (cond)
continue;
}
x; // number
}
function c(x) {
for (x = undefined; typeof x !== "number"; x = undefined) {
x; // string
if (cond)
break;
}
x; // string | number
}
@@ -0,0 +1,62 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInForStatement.ts ===
let cond: boolean;
>cond : Symbol(cond, Decl(typeGuardsInForStatement.ts, 0, 3))
function a(x: string | number) {
>a : Symbol(a, Decl(typeGuardsInForStatement.ts, 0, 18))
>x : Symbol(x, Decl(typeGuardsInForStatement.ts, 1, 11))
for (x = undefined; typeof x !== "number"; x = undefined) {
>x : Symbol(x, Decl(typeGuardsInForStatement.ts, 1, 11))
>undefined : Symbol(undefined)
>x : Symbol(x, Decl(typeGuardsInForStatement.ts, 1, 11))
>x : Symbol(x, Decl(typeGuardsInForStatement.ts, 1, 11))
>undefined : Symbol(undefined)
x; // string
>x : Symbol(x, Decl(typeGuardsInForStatement.ts, 1, 11))
}
x; // number
>x : Symbol(x, Decl(typeGuardsInForStatement.ts, 1, 11))
}
function b(x: string | number) {
>b : Symbol(b, Decl(typeGuardsInForStatement.ts, 6, 1))
>x : Symbol(x, Decl(typeGuardsInForStatement.ts, 7, 11))
for (x = undefined; typeof x !== "number"; x = undefined) {
>x : Symbol(x, Decl(typeGuardsInForStatement.ts, 7, 11))
>undefined : Symbol(undefined)
>x : Symbol(x, Decl(typeGuardsInForStatement.ts, 7, 11))
>x : Symbol(x, Decl(typeGuardsInForStatement.ts, 7, 11))
>undefined : Symbol(undefined)
x; // string
>x : Symbol(x, Decl(typeGuardsInForStatement.ts, 7, 11))
if (cond) continue;
>cond : Symbol(cond, Decl(typeGuardsInForStatement.ts, 0, 3))
}
x; // number
>x : Symbol(x, Decl(typeGuardsInForStatement.ts, 7, 11))
}
function c(x: string | number) {
>c : Symbol(c, Decl(typeGuardsInForStatement.ts, 13, 1))
>x : Symbol(x, Decl(typeGuardsInForStatement.ts, 14, 11))
for (x = undefined; typeof x !== "number"; x = undefined) {
>x : Symbol(x, Decl(typeGuardsInForStatement.ts, 14, 11))
>undefined : Symbol(undefined)
>x : Symbol(x, Decl(typeGuardsInForStatement.ts, 14, 11))
>x : Symbol(x, Decl(typeGuardsInForStatement.ts, 14, 11))
>undefined : Symbol(undefined)
x; // string
>x : Symbol(x, Decl(typeGuardsInForStatement.ts, 14, 11))
if (cond) break;
>cond : Symbol(cond, Decl(typeGuardsInForStatement.ts, 0, 3))
}
x; // string | number
>x : Symbol(x, Decl(typeGuardsInForStatement.ts, 14, 11))
}
@@ -0,0 +1,77 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInForStatement.ts ===
let cond: boolean;
>cond : boolean
function a(x: string | number) {
>a : (x: string | number) => void
>x : string | number
for (x = undefined; typeof x !== "number"; x = undefined) {
>x = undefined : undefined
>x : string | number
>undefined : undefined
>typeof x !== "number" : boolean
>typeof x : string
>x : string | number
>"number" : string
>x = undefined : undefined
>x : string | number
>undefined : undefined
x; // string
>x : string
}
x; // number
>x : number
}
function b(x: string | number) {
>b : (x: string | number) => void
>x : string | number
for (x = undefined; typeof x !== "number"; x = undefined) {
>x = undefined : undefined
>x : string | number
>undefined : undefined
>typeof x !== "number" : boolean
>typeof x : string
>x : string | number
>"number" : string
>x = undefined : undefined
>x : string | number
>undefined : undefined
x; // string
>x : string
if (cond) continue;
>cond : boolean
}
x; // number
>x : number
}
function c(x: string | number) {
>c : (x: string | number) => void
>x : string | number
for (x = undefined; typeof x !== "number"; x = undefined) {
>x = undefined : undefined
>x : string | number
>undefined : undefined
>typeof x !== "number" : boolean
>typeof x : string
>x : string | number
>"number" : string
>x = undefined : undefined
>x : string | number
>undefined : undefined
x; // string
>x : string
if (cond) break;
>cond : boolean
}
x; // string | number
>x : number | string
}
@@ -0,0 +1,153 @@
tests/cases/conformance/expressions/typeGuards/typeGuardsInIfStatement.ts(22,10): error TS2354: No best common type exists among return expressions.
tests/cases/conformance/expressions/typeGuards/typeGuardsInIfStatement.ts(31,10): error TS2354: No best common type exists among return expressions.
tests/cases/conformance/expressions/typeGuards/typeGuardsInIfStatement.ts(49,10): error TS2354: No best common type exists among return expressions.
==== tests/cases/conformance/expressions/typeGuards/typeGuardsInIfStatement.ts (3 errors) ====
// In the true branch statement of an 'if' statement,
// the type of a variable or parameter is narrowed by any type guard in the 'if' condition when true.
// In the false branch statement of an 'if' statement,
// the type of a variable or parameter is narrowed by any type guard in the 'if' condition when false.
function foo(x: number | string) {
if (typeof x === "string") {
return x.length; // string
}
else {
return x++; // number
}
}
function foo2(x: number | string) {
if (typeof x === "string") {
x = 10;
return x; // number
}
else {
return x; // number
}
}
function foo3(x: number | string) {
~~~~
!!! error TS2354: No best common type exists among return expressions.
if (typeof x === "string") {
x = "Hello";
return x; // string
}
else {
return x; // number
}
}
function foo4(x: number | string) {
~~~~
!!! error TS2354: No best common type exists among return expressions.
if (typeof x === "string") {
return x; // string
}
else {
x = 10;
return x; // number
}
}
function foo5(x: number | string) {
if (typeof x === "string") {
return x; // string
}
else {
x = "hello";
return x; // string
}
}
function foo6(x: number | string) {
~~~~
!!! error TS2354: No best common type exists among return expressions.
if (typeof x === "string") {
x = 10;
return x; // number
}
else {
x = "hello";
return x; // string
}
}
function foo7(x: number | string | boolean) {
if (typeof x === "string") {
return x === "hello"; // string
}
else if (typeof x === "boolean") {
return x; // boolean
}
else {
return x == 10; // number
}
}
function foo8(x: number | string | boolean) {
if (typeof x === "string") {
return x === "hello"; // string
}
else {
var b: number | boolean = x; // number | boolean
if (typeof x === "boolean") {
return x; // boolean
}
else {
return x == 10; // number
}
}
}
function foo9(x: number | string) {
var y = 10;
if (typeof x === "string") {
// usage of x or assignment to separate variable shouldn't cause narrowing of type to stop
y = x.length;
return x === "hello"; // string
}
else {
return x == 10; // number
}
}
function foo10(x: number | string | boolean) {
// Mixing typeguard narrowing in if statement with conditional expression typeguard
if (typeof x === "string") {
return x === "hello"; // string
}
else {
var y: boolean | string;
var b = x; // number | boolean
return typeof x === "number"
? x === 10 // number
: x; // x should be boolean
}
}
function foo11(x: number | string | boolean) {
// Mixing typeguard narrowing in if statement with conditional expression typeguard
// Assigning value to x deep inside another guard stops narrowing of type too
if (typeof x === "string") {
return x; // string | number | boolean - x changed in else branch
}
else {
var y: number| boolean | string;
var b = x; // number | boolean | string - because below we are changing value of x in if statement
return typeof x === "number"
? (
// change value of x
x = 10 && x.toString() // number | boolean | string
)
: (
// do not change value
y = x && x.toString() // number | boolean | string
);
}
}
function foo12(x: number | string | boolean) {
// Mixing typeguard narrowing in if statement with conditional expression typeguard
// Assigning value to x in outer guard shouldn't stop narrowing in the inner expression
if (typeof x === "string") {
return x.toString(); // string | number | boolean - x changed in else branch
}
else {
x = 10;
var b = x; // number | boolean | string
return typeof x === "number"
? x.toString() // number
: x.toString(); // boolean | string
}
}
@@ -1,10 +1,8 @@
//// [typeGuardsInIfStatement.ts]
// In the true branch statement of an 'if' statement,
// the type of a variable or parameter is narrowed by any type guard in the 'if' condition when true,
// provided the true branch statement contains no assignments to the variable or parameter.
// the type of a variable or parameter is narrowed by any type guard in the 'if' condition when true.
// In the false branch statement of an 'if' statement,
// the type of a variable or parameter is narrowed by any type guard in the 'if' condition when false,
// provided the false branch statement contains no assignments to the variable or parameter
// the type of a variable or parameter is narrowed by any type guard in the 'if' condition when false.
function foo(x: number | string) {
if (typeof x === "string") {
return x.length; // string
@@ -14,54 +12,49 @@ function foo(x: number | string) {
}
}
function foo2(x: number | string) {
// x is assigned in the if true branch, the type is not narrowed
if (typeof x === "string") {
x = 10;
return x; // string | number
return x; // number
}
else {
return x; // string | number
return x; // number
}
}
function foo3(x: number | string) {
// x is assigned in the if true branch, the type is not narrowed
if (typeof x === "string") {
x = "Hello"; // even though assigned using same type as narrowed expression
return x; // string | number
x = "Hello";
return x; // string
}
else {
return x; // string | number
return x; // number
}
}
function foo4(x: number | string) {
// false branch updates the variable - so here it is not number
if (typeof x === "string") {
return x; // string | number
return x; // string
}
else {
x = 10; // even though assigned number - this should result in x to be string | number
return x; // string | number
x = 10;
return x; // number
}
}
function foo5(x: number | string) {
// false branch updates the variable - so here it is not number
if (typeof x === "string") {
return x; // string | number
return x; // string
}
else {
x = "hello";
return x; // string | number
return x; // string
}
}
function foo6(x: number | string) {
// Modify in both branches
if (typeof x === "string") {
x = 10;
return x; // string | number
return x; // number
}
else {
x = "hello";
return x; // string | number
return x; // string
}
}
function foo7(x: number | string | boolean) {
@@ -150,11 +143,9 @@ function foo12(x: number | string | boolean) {
//// [typeGuardsInIfStatement.js]
// In the true branch statement of an 'if' statement,
// the type of a variable or parameter is narrowed by any type guard in the 'if' condition when true,
// provided the true branch statement contains no assignments to the variable or parameter.
// the type of a variable or parameter is narrowed by any type guard in the 'if' condition when true.
// In the false branch statement of an 'if' statement,
// the type of a variable or parameter is narrowed by any type guard in the 'if' condition when false,
// provided the false branch statement contains no assignments to the variable or parameter
// the type of a variable or parameter is narrowed by any type guard in the 'if' condition when false.
function foo(x) {
if (typeof x === "string") {
return x.length; // string
@@ -164,54 +155,49 @@ function foo(x) {
}
}
function foo2(x) {
// x is assigned in the if true branch, the type is not narrowed
if (typeof x === "string") {
x = 10;
return x; // string | number
return x; // number
}
else {
return x; // string | number
return x; // number
}
}
function foo3(x) {
// x is assigned in the if true branch, the type is not narrowed
if (typeof x === "string") {
x = "Hello"; // even though assigned using same type as narrowed expression
return x; // string | number
x = "Hello";
return x; // string
}
else {
return x; // string | number
return x; // number
}
}
function foo4(x) {
// false branch updates the variable - so here it is not number
if (typeof x === "string") {
return x; // string | number
return x; // string
}
else {
x = 10; // even though assigned number - this should result in x to be string | number
return x; // string | number
x = 10;
return x; // number
}
}
function foo5(x) {
// false branch updates the variable - so here it is not number
if (typeof x === "string") {
return x; // string | number
return x; // string
}
else {
x = "hello";
return x; // string | number
return x; // string
}
}
function foo6(x) {
// Modify in both branches
if (typeof x === "string") {
x = 10;
return x; // string | number
return x; // number
}
else {
x = "hello";
return x; // string | number
return x; // string
}
}
function foo7(x) {
@@ -1,304 +0,0 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInIfStatement.ts ===
// In the true branch statement of an 'if' statement,
// the type of a variable or parameter is narrowed by any type guard in the 'if' condition when true,
// provided the true branch statement contains no assignments to the variable or parameter.
// In the false branch statement of an 'if' statement,
// the type of a variable or parameter is narrowed by any type guard in the 'if' condition when false,
// provided the false branch statement contains no assignments to the variable or parameter
function foo(x: number | string) {
>foo : Symbol(foo, Decl(typeGuardsInIfStatement.ts, 0, 0))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 6, 13))
if (typeof x === "string") {
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 6, 13))
return x.length; // string
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 6, 13))
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
}
else {
return x++; // number
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 6, 13))
}
}
function foo2(x: number | string) {
>foo2 : Symbol(foo2, Decl(typeGuardsInIfStatement.ts, 13, 1))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 14, 14))
// x is assigned in the if true branch, the type is not narrowed
if (typeof x === "string") {
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 14, 14))
x = 10;
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 14, 14))
return x; // string | number
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 14, 14))
}
else {
return x; // string | number
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 14, 14))
}
}
function foo3(x: number | string) {
>foo3 : Symbol(foo3, Decl(typeGuardsInIfStatement.ts, 23, 1))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 24, 14))
// x is assigned in the if true branch, the type is not narrowed
if (typeof x === "string") {
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 24, 14))
x = "Hello"; // even though assigned using same type as narrowed expression
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 24, 14))
return x; // string | number
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 24, 14))
}
else {
return x; // string | number
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 24, 14))
}
}
function foo4(x: number | string) {
>foo4 : Symbol(foo4, Decl(typeGuardsInIfStatement.ts, 33, 1))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 34, 14))
// false branch updates the variable - so here it is not number
if (typeof x === "string") {
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 34, 14))
return x; // string | number
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 34, 14))
}
else {
x = 10; // even though assigned number - this should result in x to be string | number
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 34, 14))
return x; // string | number
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 34, 14))
}
}
function foo5(x: number | string) {
>foo5 : Symbol(foo5, Decl(typeGuardsInIfStatement.ts, 43, 1))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 44, 14))
// false branch updates the variable - so here it is not number
if (typeof x === "string") {
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 44, 14))
return x; // string | number
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 44, 14))
}
else {
x = "hello";
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 44, 14))
return x; // string | number
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 44, 14))
}
}
function foo6(x: number | string) {
>foo6 : Symbol(foo6, Decl(typeGuardsInIfStatement.ts, 53, 1))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 54, 14))
// Modify in both branches
if (typeof x === "string") {
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 54, 14))
x = 10;
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 54, 14))
return x; // string | number
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 54, 14))
}
else {
x = "hello";
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 54, 14))
return x; // string | number
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 54, 14))
}
}
function foo7(x: number | string | boolean) {
>foo7 : Symbol(foo7, Decl(typeGuardsInIfStatement.ts, 64, 1))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 65, 14))
if (typeof x === "string") {
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 65, 14))
return x === "hello"; // string
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 65, 14))
}
else if (typeof x === "boolean") {
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 65, 14))
return x; // boolean
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 65, 14))
}
else {
return x == 10; // number
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 65, 14))
}
}
function foo8(x: number | string | boolean) {
>foo8 : Symbol(foo8, Decl(typeGuardsInIfStatement.ts, 75, 1))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14))
if (typeof x === "string") {
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14))
return x === "hello"; // string
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14))
}
else {
var b: number | boolean = x; // number | boolean
>b : Symbol(b, Decl(typeGuardsInIfStatement.ts, 81, 11))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14))
if (typeof x === "boolean") {
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14))
return x; // boolean
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14))
}
else {
return x == 10; // number
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14))
}
}
}
function foo9(x: number | string) {
>foo9 : Symbol(foo9, Decl(typeGuardsInIfStatement.ts, 89, 1))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 90, 14))
var y = 10;
>y : Symbol(y, Decl(typeGuardsInIfStatement.ts, 91, 7))
if (typeof x === "string") {
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 90, 14))
// usage of x or assignment to separate variable shouldn't cause narrowing of type to stop
y = x.length;
>y : Symbol(y, Decl(typeGuardsInIfStatement.ts, 91, 7))
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 90, 14))
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
return x === "hello"; // string
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 90, 14))
}
else {
return x == 10; // number
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 90, 14))
}
}
function foo10(x: number | string | boolean) {
>foo10 : Symbol(foo10, Decl(typeGuardsInIfStatement.ts, 100, 1))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15))
// Mixing typeguard narrowing in if statement with conditional expression typeguard
if (typeof x === "string") {
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15))
return x === "hello"; // string
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15))
}
else {
var y: boolean | string;
>y : Symbol(y, Decl(typeGuardsInIfStatement.ts, 107, 11))
var b = x; // number | boolean
>b : Symbol(b, Decl(typeGuardsInIfStatement.ts, 108, 11))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15))
return typeof x === "number"
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15))
? x === 10 // number
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15))
: x; // x should be boolean
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15))
}
}
function foo11(x: number | string | boolean) {
>foo11 : Symbol(foo11, Decl(typeGuardsInIfStatement.ts, 113, 1))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15))
// Mixing typeguard narrowing in if statement with conditional expression typeguard
// Assigning value to x deep inside another guard stops narrowing of type too
if (typeof x === "string") {
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15))
return x; // string | number | boolean - x changed in else branch
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15))
}
else {
var y: number| boolean | string;
>y : Symbol(y, Decl(typeGuardsInIfStatement.ts, 121, 11))
var b = x; // number | boolean | string - because below we are changing value of x in if statement
>b : Symbol(b, Decl(typeGuardsInIfStatement.ts, 122, 11))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15))
return typeof x === "number"
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15))
? (
// change value of x
x = 10 && x.toString() // number | boolean | string
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15))
>x.toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15))
>toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
)
: (
// do not change value
y = x && x.toString() // number | boolean | string
>y : Symbol(y, Decl(typeGuardsInIfStatement.ts, 121, 11))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15))
>x.toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15))
>toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
);
}
}
function foo12(x: number | string | boolean) {
>foo12 : Symbol(foo12, Decl(typeGuardsInIfStatement.ts, 133, 1))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15))
// Mixing typeguard narrowing in if statement with conditional expression typeguard
// Assigning value to x in outer guard shouldn't stop narrowing in the inner expression
if (typeof x === "string") {
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15))
return x.toString(); // string | number | boolean - x changed in else branch
>x.toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15))
>toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
}
else {
x = 10;
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15))
var b = x; // number | boolean | string
>b : Symbol(b, Decl(typeGuardsInIfStatement.ts, 142, 11))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15))
return typeof x === "number"
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15))
? x.toString() // number
>x.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15))
>toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
: x.toString(); // boolean | string
>x.toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15))
>toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
}
}
@@ -1,405 +0,0 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInIfStatement.ts ===
// In the true branch statement of an 'if' statement,
// the type of a variable or parameter is narrowed by any type guard in the 'if' condition when true,
// provided the true branch statement contains no assignments to the variable or parameter.
// In the false branch statement of an 'if' statement,
// the type of a variable or parameter is narrowed by any type guard in the 'if' condition when false,
// provided the false branch statement contains no assignments to the variable or parameter
function foo(x: number | string) {
>foo : (x: number | string) => number
>x : number | string
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
return x.length; // string
>x.length : number
>x : string
>length : number
}
else {
return x++; // number
>x++ : number
>x : number
}
}
function foo2(x: number | string) {
>foo2 : (x: number | string) => number | string
>x : number | string
// x is assigned in the if true branch, the type is not narrowed
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
x = 10;
>x = 10 : number
>x : number | string
>10 : number
return x; // string | number
>x : number | string
}
else {
return x; // string | number
>x : number | string
}
}
function foo3(x: number | string) {
>foo3 : (x: number | string) => number | string
>x : number | string
// x is assigned in the if true branch, the type is not narrowed
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
x = "Hello"; // even though assigned using same type as narrowed expression
>x = "Hello" : string
>x : number | string
>"Hello" : string
return x; // string | number
>x : number | string
}
else {
return x; // string | number
>x : number | string
}
}
function foo4(x: number | string) {
>foo4 : (x: number | string) => number | string
>x : number | string
// false branch updates the variable - so here it is not number
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
return x; // string | number
>x : number | string
}
else {
x = 10; // even though assigned number - this should result in x to be string | number
>x = 10 : number
>x : number | string
>10 : number
return x; // string | number
>x : number | string
}
}
function foo5(x: number | string) {
>foo5 : (x: number | string) => number | string
>x : number | string
// false branch updates the variable - so here it is not number
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
return x; // string | number
>x : number | string
}
else {
x = "hello";
>x = "hello" : string
>x : number | string
>"hello" : string
return x; // string | number
>x : number | string
}
}
function foo6(x: number | string) {
>foo6 : (x: number | string) => number | string
>x : number | string
// Modify in both branches
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
x = 10;
>x = 10 : number
>x : number | string
>10 : number
return x; // string | number
>x : number | string
}
else {
x = "hello";
>x = "hello" : string
>x : number | string
>"hello" : string
return x; // string | number
>x : number | string
}
}
function foo7(x: number | string | boolean) {
>foo7 : (x: number | string | boolean) => boolean
>x : number | string | boolean
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : number | string | boolean
>"string" : string
return x === "hello"; // string
>x === "hello" : boolean
>x : string
>"hello" : string
}
else if (typeof x === "boolean") {
>typeof x === "boolean" : boolean
>typeof x : string
>x : number | boolean
>"boolean" : string
return x; // boolean
>x : boolean
}
else {
return x == 10; // number
>x == 10 : boolean
>x : number
>10 : number
}
}
function foo8(x: number | string | boolean) {
>foo8 : (x: number | string | boolean) => boolean
>x : number | string | boolean
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : number | string | boolean
>"string" : string
return x === "hello"; // string
>x === "hello" : boolean
>x : string
>"hello" : string
}
else {
var b: number | boolean = x; // number | boolean
>b : number | boolean
>x : number | boolean
if (typeof x === "boolean") {
>typeof x === "boolean" : boolean
>typeof x : string
>x : number | boolean
>"boolean" : string
return x; // boolean
>x : boolean
}
else {
return x == 10; // number
>x == 10 : boolean
>x : number
>10 : number
}
}
}
function foo9(x: number | string) {
>foo9 : (x: number | string) => boolean
>x : number | string
var y = 10;
>y : number
>10 : number
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
// usage of x or assignment to separate variable shouldn't cause narrowing of type to stop
y = x.length;
>y = x.length : number
>y : number
>x.length : number
>x : string
>length : number
return x === "hello"; // string
>x === "hello" : boolean
>x : string
>"hello" : string
}
else {
return x == 10; // number
>x == 10 : boolean
>x : number
>10 : number
}
}
function foo10(x: number | string | boolean) {
>foo10 : (x: number | string | boolean) => boolean
>x : number | string | boolean
// Mixing typeguard narrowing in if statement with conditional expression typeguard
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : number | string | boolean
>"string" : string
return x === "hello"; // string
>x === "hello" : boolean
>x : string
>"hello" : string
}
else {
var y: boolean | string;
>y : boolean | string
var b = x; // number | boolean
>b : number | boolean
>x : number | boolean
return typeof x === "number"
>typeof x === "number" ? x === 10 // number : x : boolean
>typeof x === "number" : boolean
>typeof x : string
>x : number | boolean
>"number" : string
? x === 10 // number
>x === 10 : boolean
>x : number
>10 : number
: x; // x should be boolean
>x : boolean
}
}
function foo11(x: number | string | boolean) {
>foo11 : (x: number | string | boolean) => number | string | boolean
>x : number | string | boolean
// Mixing typeguard narrowing in if statement with conditional expression typeguard
// Assigning value to x deep inside another guard stops narrowing of type too
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : number | string | boolean
>"string" : string
return x; // string | number | boolean - x changed in else branch
>x : number | string | boolean
}
else {
var y: number| boolean | string;
>y : number | boolean | string
var b = x; // number | boolean | string - because below we are changing value of x in if statement
>b : number | string | boolean
>x : number | string | boolean
return typeof x === "number"
>typeof x === "number" ? ( // change value of x x = 10 && x.toString() // number | boolean | string ) : ( // do not change value y = x && x.toString() // number | boolean | string ) : string
>typeof x === "number" : boolean
>typeof x : string
>x : number | string | boolean
>"number" : string
? (
>( // change value of x x = 10 && x.toString() // number | boolean | string ) : string
// change value of x
x = 10 && x.toString() // number | boolean | string
>x = 10 && x.toString() : string
>x : number | string | boolean
>10 && x.toString() : string
>10 : number
>x.toString() : string
>x.toString : (radix?: number) => string
>x : number | string | boolean
>toString : (radix?: number) => string
)
: (
>( // do not change value y = x && x.toString() // number | boolean | string ) : string
// do not change value
y = x && x.toString() // number | boolean | string
>y = x && x.toString() : string
>y : number | boolean | string
>x && x.toString() : string
>x : number | string | boolean
>x.toString() : string
>x.toString : (radix?: number) => string
>x : number | string | boolean
>toString : (radix?: number) => string
);
}
}
function foo12(x: number | string | boolean) {
>foo12 : (x: number | string | boolean) => string
>x : number | string | boolean
// Mixing typeguard narrowing in if statement with conditional expression typeguard
// Assigning value to x in outer guard shouldn't stop narrowing in the inner expression
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : number | string | boolean
>"string" : string
return x.toString(); // string | number | boolean - x changed in else branch
>x.toString() : string
>x.toString : (radix?: number) => string
>x : number | string | boolean
>toString : (radix?: number) => string
}
else {
x = 10;
>x = 10 : number
>x : number | string | boolean
>10 : number
var b = x; // number | boolean | string
>b : number | string | boolean
>x : number | string | boolean
return typeof x === "number"
>typeof x === "number" ? x.toString() // number : x.toString() : string
>typeof x === "number" : boolean
>typeof x : string
>x : number | string | boolean
>"number" : string
? x.toString() // number
>x.toString() : string
>x.toString : (radix?: number) => string
>x : number
>toString : (radix?: number) => string
: x.toString(); // boolean | string
>x.toString() : string
>x.toString : () => string
>x : string | boolean
>toString : () => string
}
}
@@ -1,7 +1,6 @@
//// [typeGuardsInRightOperandOfAndAndOperator.ts]
// In the right operand of a && operation,
// the type of a variable or parameter is narrowed by any type guard in the left operand when true,
// provided the right operand contains no assignments to the variable or parameter.
// the type of a variable or parameter is narrowed by any type guard in the left operand when true.
function foo(x: number | string) {
return typeof x === "string" && x.length === 10; // string
}
@@ -36,29 +35,19 @@ function foo7(x: number | string | boolean) {
var y: number| boolean | string;
var z: number| boolean | string;
// Mixing typeguard narrowing
// Assigning value to x deep inside another guard stops narrowing of type too
return typeof x !== "string"
&& ((z = x) // string | number | boolean - x changed deeper in conditional expression
&& ((z = x) // number | boolean
&& (typeof x === "number"
// change value of x
? (x = 10 && x.toString()) // number | boolean | string
? ((x = 10) && x.toString()) // x is number
// do not change value
: (y = x && x.toString()))); // number | boolean | string
: ((y = x) && x.toString()))); // x is boolean
}
function foo8(x: number | string) {
// Mixing typeguard
// Assigning value to x in outer guard shouldn't stop narrowing in the inner expression
return typeof x !== "string"
&& (x = 10) // change x - number| string
&& (typeof x === "number"
? x // number
: x.length); // string
}
//// [typeGuardsInRightOperandOfAndAndOperator.js]
// In the right operand of a && operation,
// the type of a variable or parameter is narrowed by any type guard in the left operand when true,
// provided the right operand contains no assignments to the variable or parameter.
// the type of a variable or parameter is narrowed by any type guard in the left operand when true.
function foo(x) {
return typeof x === "string" && x.length === 10; // string
}
@@ -93,19 +82,9 @@ function foo7(x) {
var y;
var z;
// Mixing typeguard narrowing
// Assigning value to x deep inside another guard stops narrowing of type too
return typeof x !== "string"
&& ((z = x) // string | number | boolean - x changed deeper in conditional expression
&& ((z = x) // number | boolean
&& (typeof x === "number"
? (x = 10 && x.toString()) // number | boolean | string
: (y = x && x.toString()))); // number | boolean | string
}
function foo8(x) {
// Mixing typeguard
// Assigning value to x in outer guard shouldn't stop narrowing in the inner expression
return typeof x !== "string"
&& (x = 10) // change x - number| string
&& (typeof x === "number"
? x // number
: x.length); // string
? ((x = 10) && x.toString()) // x is number
: ((y = x) && x.toString()))); // x is boolean
}
@@ -1,143 +1,119 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfAndAndOperator.ts ===
// In the right operand of a && operation,
// the type of a variable or parameter is narrowed by any type guard in the left operand when true,
// provided the right operand contains no assignments to the variable or parameter.
// the type of a variable or parameter is narrowed by any type guard in the left operand when true.
function foo(x: number | string) {
>foo : Symbol(foo, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 0, 0))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 3, 13))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 2, 13))
return typeof x === "string" && x.length === 10; // string
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 3, 13))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 2, 13))
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 3, 13))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 2, 13))
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
}
function foo2(x: number | string) {
>foo2 : Symbol(foo2, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 5, 1))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 6, 14))
>foo2 : Symbol(foo2, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 4, 1))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 5, 14))
// modify x in right hand operand
return typeof x === "string" && ((x = 10) && x); // string | number
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 6, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 6, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 6, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 5, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 5, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 5, 14))
}
function foo3(x: number | string) {
>foo3 : Symbol(foo3, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 9, 1))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 10, 14))
>foo3 : Symbol(foo3, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 8, 1))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 9, 14))
// modify x in right hand operand with string type itself
return typeof x === "string" && ((x = "hello") && x); // string | number
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 10, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 10, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 10, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 9, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 9, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 9, 14))
}
function foo4(x: number | string | boolean) {
>foo4 : Symbol(foo4, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 13, 1))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 14, 14))
>foo4 : Symbol(foo4, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 12, 1))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 13, 14))
return typeof x !== "string" // string | number | boolean
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 14, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 13, 14))
&& typeof x !== "number" // number | boolean
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 14, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 13, 14))
&& x; // boolean
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 14, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 13, 14))
}
function foo5(x: number | string | boolean) {
>foo5 : Symbol(foo5, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 18, 1))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 19, 14))
>foo5 : Symbol(foo5, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 17, 1))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 18, 14))
// usage of x or assignment to separate variable shouldn't cause narrowing of type to stop
var b: number | boolean;
>b : Symbol(b, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 21, 7))
>b : Symbol(b, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 20, 7))
return typeof x !== "string" // string | number | boolean
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 19, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 18, 14))
&& ((b = x) && (typeof x !== "number" // number | boolean
>b : Symbol(b, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 21, 7))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 19, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 19, 14))
>b : Symbol(b, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 20, 7))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 18, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 18, 14))
&& x)); // boolean
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 19, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 18, 14))
}
function foo6(x: number | string | boolean) {
>foo6 : Symbol(foo6, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 25, 1))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 26, 14))
>foo6 : Symbol(foo6, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 24, 1))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 25, 14))
// Mixing typeguard narrowing in if statement with conditional expression typeguard
return typeof x !== "string" // string | number | boolean
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 26, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 25, 14))
&& (typeof x !== "number" // number | boolean
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 26, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 25, 14))
? x // boolean
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 26, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 25, 14))
: x === 10) // number
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 26, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 25, 14))
}
function foo7(x: number | string | boolean) {
>foo7 : Symbol(foo7, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 32, 1))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14))
>foo7 : Symbol(foo7, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 31, 1))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 32, 14))
var y: number| boolean | string;
>y : Symbol(y, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 34, 7))
>y : Symbol(y, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 7))
var z: number| boolean | string;
>z : Symbol(z, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 35, 7))
>z : Symbol(z, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 34, 7))
// Mixing typeguard narrowing
// Assigning value to x deep inside another guard stops narrowing of type too
return typeof x !== "string"
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 32, 14))
&& ((z = x) // string | number | boolean - x changed deeper in conditional expression
>z : Symbol(z, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 35, 7))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14))
&& ((z = x) // number | boolean
>z : Symbol(z, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 34, 7))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 32, 14))
&& (typeof x === "number"
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 32, 14))
// change value of x
? (x = 10 && x.toString()) // number | boolean | string
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14))
>x.toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14))
>toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
? ((x = 10) && x.toString()) // x is number
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 32, 14))
>x.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 32, 14))
>toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
// do not change value
: (y = x && x.toString()))); // number | boolean | string
>y : Symbol(y, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 34, 7))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14))
>x.toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14))
>toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
: ((y = x) && x.toString()))); // x is boolean
>y : Symbol(y, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 7))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 32, 14))
>x.toString : Symbol(Object.toString, Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 32, 14))
>toString : Symbol(Object.toString, Decl(lib.d.ts, --, --))
}
function foo8(x: number | string) {
>foo8 : Symbol(foo8, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 45, 1))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 46, 14))
// Mixing typeguard
// Assigning value to x in outer guard shouldn't stop narrowing in the inner expression
return typeof x !== "string"
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 46, 14))
&& (x = 10) // change x - number| string
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 46, 14))
&& (typeof x === "number"
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 46, 14))
? x // number
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 46, 14))
: x.length); // string
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 46, 14))
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
}
@@ -1,7 +1,6 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfAndAndOperator.ts ===
// In the right operand of a && operation,
// the type of a variable or parameter is narrowed by any type guard in the left operand when true,
// provided the right operand contains no assignments to the variable or parameter.
// the type of a variable or parameter is narrowed by any type guard in the left operand when true.
function foo(x: number | string) {
>foo : (x: number | string) => boolean
>x : number | string
@@ -19,42 +18,42 @@ function foo(x: number | string) {
>10 : number
}
function foo2(x: number | string) {
>foo2 : (x: number | string) => number | string
>foo2 : (x: number | string) => number
>x : number | string
// modify x in right hand operand
return typeof x === "string" && ((x = 10) && x); // string | number
>typeof x === "string" && ((x = 10) && x) : number | string
>typeof x === "string" && ((x = 10) && x) : number
>typeof x === "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
>((x = 10) && x) : number | string
>(x = 10) && x : number | string
>((x = 10) && x) : number
>(x = 10) && x : number
>(x = 10) : number
>x = 10 : number
>x : number | string
>10 : number
>x : number | string
>x : number
}
function foo3(x: number | string) {
>foo3 : (x: number | string) => number | string
>foo3 : (x: number | string) => string
>x : number | string
// modify x in right hand operand with string type itself
return typeof x === "string" && ((x = "hello") && x); // string | number
>typeof x === "string" && ((x = "hello") && x) : number | string
>typeof x === "string" && ((x = "hello") && x) : string
>typeof x === "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
>((x = "hello") && x) : number | string
>(x = "hello") && x : number | string
>((x = "hello") && x) : string
>(x = "hello") && x : string
>(x = "hello") : string
>x = "hello" : string
>x : number | string
>"hello" : string
>x : number | string
>x : string
}
function foo4(x: number | string | boolean) {
>foo4 : (x: number | string | boolean) => boolean
@@ -148,87 +147,53 @@ function foo7(x: number | string | boolean) {
>z : number | boolean | string
// Mixing typeguard narrowing
// Assigning value to x deep inside another guard stops narrowing of type too
return typeof x !== "string"
>typeof x !== "string" && ((z = x) // string | number | boolean - x changed deeper in conditional expression && (typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString()))) : string
>typeof x !== "string" && ((z = x) // number | boolean && (typeof x === "number" // change value of x ? ((x = 10) && x.toString()) // x is number // do not change value : ((y = x) && x.toString()))) : string
>typeof x !== "string" : boolean
>typeof x : string
>x : number | string | boolean
>"string" : string
&& ((z = x) // string | number | boolean - x changed deeper in conditional expression
>((z = x) // string | number | boolean - x changed deeper in conditional expression && (typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString()))) : string
>(z = x) // string | number | boolean - x changed deeper in conditional expression && (typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString())) : string
>(z = x) : number | string | boolean
>z = x : number | string | boolean
&& ((z = x) // number | boolean
>((z = x) // number | boolean && (typeof x === "number" // change value of x ? ((x = 10) && x.toString()) // x is number // do not change value : ((y = x) && x.toString()))) : string
>(z = x) // number | boolean && (typeof x === "number" // change value of x ? ((x = 10) && x.toString()) // x is number // do not change value : ((y = x) && x.toString())) : string
>(z = x) : number | boolean
>z = x : number | boolean
>z : number | boolean | string
>x : number | string | boolean
>x : number | boolean
&& (typeof x === "number"
>(typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString())) : string
>typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString()) : string
>(typeof x === "number" // change value of x ? ((x = 10) && x.toString()) // x is number // do not change value : ((y = x) && x.toString())) : string
>typeof x === "number" // change value of x ? ((x = 10) && x.toString()) // x is number // do not change value : ((y = x) && x.toString()) : string
>typeof x === "number" : boolean
>typeof x : string
>x : number | string | boolean
>x : number | boolean
>"number" : string
// change value of x
? (x = 10 && x.toString()) // number | boolean | string
>(x = 10 && x.toString()) : string
>x = 10 && x.toString() : string
? ((x = 10) && x.toString()) // x is number
>((x = 10) && x.toString()) : string
>(x = 10) && x.toString() : string
>(x = 10) : number
>x = 10 : number
>x : number | string | boolean
>10 && x.toString() : string
>10 : number
>x.toString() : string
>x.toString : (radix?: number) => string
>x : number | string | boolean
>x : number
>toString : (radix?: number) => string
// do not change value
: (y = x && x.toString()))); // number | boolean | string
>(y = x && x.toString()) : string
>y = x && x.toString() : string
: ((y = x) && x.toString()))); // x is boolean
>((y = x) && x.toString()) : string
>(y = x) && x.toString() : string
>(y = x) : boolean
>y = x : boolean
>y : number | boolean | string
>x && x.toString() : string
>x : number | string | boolean
>x : boolean
>x.toString() : string
>x.toString : (radix?: number) => string
>x : number | string | boolean
>toString : (radix?: number) => string
>x.toString : () => string
>x : boolean
>toString : () => string
}
function foo8(x: number | string) {
>foo8 : (x: number | string) => number
>x : number | string
// Mixing typeguard
// Assigning value to x in outer guard shouldn't stop narrowing in the inner expression
return typeof x !== "string"
>typeof x !== "string" && (x = 10) // change x - number| string && (typeof x === "number" ? x // number : x.length) : number
>typeof x !== "string" && (x = 10) : number
>typeof x !== "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
&& (x = 10) // change x - number| string
>(x = 10) : number
>x = 10 : number
>x : number | string
>10 : number
&& (typeof x === "number"
>(typeof x === "number" ? x // number : x.length) : number
>typeof x === "number" ? x // number : x.length : number
>typeof x === "number" : boolean
>typeof x : string
>x : number | string
>"number" : string
? x // number
>x : number
: x.length); // string
>x.length : number
>x : string
>length : number
}
@@ -36,24 +36,15 @@ function foo7(x: number | string | boolean) {
var y: number| boolean | string;
var z: number| boolean | string;
// Mixing typeguard narrowing
// Assigning value to x deep inside another guard stops narrowing of type too
return typeof x === "string"
|| ((z = x) // string | number | boolean - x changed deeper in conditional expression
|| ((z = x) // number | boolean
|| (typeof x === "number"
// change value of x
? (x = 10 && x.toString()) // number | boolean | string
? ((x = 10) && x.toString()) // number | boolean | string
// do not change value
: (y = x && x.toString()))); // number | boolean | string
: ((y = x) && x.toString()))); // number | boolean | string
}
function foo8(x: number | string) {
// Mixing typeguard
// Assigning value to x in outer guard shouldn't stop narrowing in the inner expression
return typeof x === "string"
|| (x = 10) // change x - number| string
|| (typeof x === "number"
? x // number
: x.length); // string
}
//// [typeGuardsInRightOperandOfOrOrOperator.js]
// In the right operand of a || operation,
@@ -93,19 +84,9 @@ function foo7(x) {
var y;
var z;
// Mixing typeguard narrowing
// Assigning value to x deep inside another guard stops narrowing of type too
return typeof x === "string"
|| ((z = x) // string | number | boolean - x changed deeper in conditional expression
|| ((z = x) // number | boolean
|| (typeof x === "number"
? (x = 10 && x.toString()) // number | boolean | string
: (y = x && x.toString()))); // number | boolean | string
}
function foo8(x) {
// Mixing typeguard
// Assigning value to x in outer guard shouldn't stop narrowing in the inner expression
return typeof x === "string"
|| (x = 10) // change x - number| string
|| (typeof x === "number"
? x // number
: x.length); // string
? ((x = 10) && x.toString()) // number | boolean | string
: ((y = x) && x.toString()))); // number | boolean | string
}
@@ -92,11 +92,10 @@ function foo7(x: number | string | boolean) {
>z : Symbol(z, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 35, 7))
// Mixing typeguard narrowing
// Assigning value to x deep inside another guard stops narrowing of type too
return typeof x === "string"
>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14))
|| ((z = x) // string | number | boolean - x changed deeper in conditional expression
|| ((z = x) // number | boolean
>z : Symbol(z, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 35, 7))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14))
@@ -104,40 +103,18 @@ function foo7(x: number | string | boolean) {
>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14))
// change value of x
? (x = 10 && x.toString()) // number | boolean | string
? ((x = 10) && x.toString()) // number | boolean | string
>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14))
>x.toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>x.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14))
>toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
// do not change value
: (y = x && x.toString()))); // number | boolean | string
: ((y = x) && x.toString()))); // number | boolean | string
>y : Symbol(y, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 34, 7))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14))
>x.toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>x.toString : Symbol(Object.toString, Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14))
>toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>toString : Symbol(Object.toString, Decl(lib.d.ts, --, --))
}
function foo8(x: number | string) {
>foo8 : Symbol(foo8, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 45, 1))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 46, 14))
// Mixing typeguard
// Assigning value to x in outer guard shouldn't stop narrowing in the inner expression
return typeof x === "string"
>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 46, 14))
|| (x = 10) // change x - number| string
>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 46, 14))
|| (typeof x === "number"
>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 46, 14))
? x // number
>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 46, 14))
: x.length); // string
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 46, 14))
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
}
@@ -19,42 +19,42 @@ function foo(x: number | string) {
>10 : number
}
function foo2(x: number | string) {
>foo2 : (x: number | string) => boolean | number | string
>foo2 : (x: number | string) => boolean | number
>x : number | string
// modify x in right hand operand
return typeof x !== "string" || ((x = 10) || x); // string | number
>typeof x !== "string" || ((x = 10) || x) : boolean | number | string
>typeof x !== "string" || ((x = 10) || x) : boolean | number
>typeof x !== "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
>((x = 10) || x) : number | string
>(x = 10) || x : number | string
>((x = 10) || x) : number
>(x = 10) || x : number
>(x = 10) : number
>x = 10 : number
>x : number | string
>10 : number
>x : number | string
>x : number
}
function foo3(x: number | string) {
>foo3 : (x: number | string) => boolean | string | number
>foo3 : (x: number | string) => boolean | string
>x : number | string
// modify x in right hand operand with string type itself
return typeof x !== "string" || ((x = "hello") || x); // string | number
>typeof x !== "string" || ((x = "hello") || x) : boolean | string | number
>typeof x !== "string" || ((x = "hello") || x) : boolean | string
>typeof x !== "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
>((x = "hello") || x) : string | number
>(x = "hello") || x : string | number
>((x = "hello") || x) : string
>(x = "hello") || x : string
>(x = "hello") : string
>x = "hello" : string
>x : number | string
>"hello" : string
>x : number | string
>x : string
}
function foo4(x: number | string | boolean) {
>foo4 : (x: number | string | boolean) => boolean
@@ -148,87 +148,53 @@ function foo7(x: number | string | boolean) {
>z : number | boolean | string
// Mixing typeguard narrowing
// Assigning value to x deep inside another guard stops narrowing of type too
return typeof x === "string"
>typeof x === "string" || ((z = x) // string | number | boolean - x changed deeper in conditional expression || (typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString()))) : boolean | number | string
>typeof x === "string" || ((z = x) // number | boolean || (typeof x === "number" // change value of x ? ((x = 10) && x.toString()) // number | boolean | string // do not change value : ((y = x) && x.toString()))) : boolean | number | string
>typeof x === "string" : boolean
>typeof x : string
>x : number | string | boolean
>"string" : string
|| ((z = x) // string | number | boolean - x changed deeper in conditional expression
>((z = x) // string | number | boolean - x changed deeper in conditional expression || (typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString()))) : number | string | boolean
>(z = x) // string | number | boolean - x changed deeper in conditional expression || (typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString())) : number | string | boolean
>(z = x) : number | string | boolean
>z = x : number | string | boolean
|| ((z = x) // number | boolean
>((z = x) // number | boolean || (typeof x === "number" // change value of x ? ((x = 10) && x.toString()) // number | boolean | string // do not change value : ((y = x) && x.toString()))) : number | boolean | string
>(z = x) // number | boolean || (typeof x === "number" // change value of x ? ((x = 10) && x.toString()) // number | boolean | string // do not change value : ((y = x) && x.toString())) : number | boolean | string
>(z = x) : number | boolean
>z = x : number | boolean
>z : number | boolean | string
>x : number | string | boolean
>x : number | boolean
|| (typeof x === "number"
>(typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString())) : string
>typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString()) : string
>(typeof x === "number" // change value of x ? ((x = 10) && x.toString()) // number | boolean | string // do not change value : ((y = x) && x.toString())) : string
>typeof x === "number" // change value of x ? ((x = 10) && x.toString()) // number | boolean | string // do not change value : ((y = x) && x.toString()) : string
>typeof x === "number" : boolean
>typeof x : string
>x : number | string | boolean
>x : number | boolean
>"number" : string
// change value of x
? (x = 10 && x.toString()) // number | boolean | string
>(x = 10 && x.toString()) : string
>x = 10 && x.toString() : string
? ((x = 10) && x.toString()) // number | boolean | string
>((x = 10) && x.toString()) : string
>(x = 10) && x.toString() : string
>(x = 10) : number
>x = 10 : number
>x : number | string | boolean
>10 && x.toString() : string
>10 : number
>x.toString() : string
>x.toString : (radix?: number) => string
>x : number | string | boolean
>x : number
>toString : (radix?: number) => string
// do not change value
: (y = x && x.toString()))); // number | boolean | string
>(y = x && x.toString()) : string
>y = x && x.toString() : string
: ((y = x) && x.toString()))); // number | boolean | string
>((y = x) && x.toString()) : string
>(y = x) && x.toString() : string
>(y = x) : boolean
>y = x : boolean
>y : number | boolean | string
>x && x.toString() : string
>x : number | string | boolean
>x : boolean
>x.toString() : string
>x.toString : (radix?: number) => string
>x : number | string | boolean
>toString : (radix?: number) => string
>x.toString : () => string
>x : boolean
>toString : () => string
}
function foo8(x: number | string) {
>foo8 : (x: number | string) => boolean | number
>x : number | string
// Mixing typeguard
// Assigning value to x in outer guard shouldn't stop narrowing in the inner expression
return typeof x === "string"
>typeof x === "string" || (x = 10) // change x - number| string || (typeof x === "number" ? x // number : x.length) : boolean | number
>typeof x === "string" || (x = 10) : boolean | number
>typeof x === "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
|| (x = 10) // change x - number| string
>(x = 10) : number
>x = 10 : number
>x : number | string
>10 : number
|| (typeof x === "number"
>(typeof x === "number" ? x // number : x.length) : number
>typeof x === "number" ? x // number : x.length : number
>typeof x === "number" : boolean
>typeof x : string
>x : number | string
>"number" : string
? x // number
>x : number
: x.length); // string
>x.length : number
>x : string
>length : number
}
@@ -0,0 +1,54 @@
//// [typeGuardsInWhileStatement.ts]
let cond: boolean;
function a(x: string | number) {
while (typeof x === "string") {
x; // string
x = undefined;
}
x; // number
}
function b(x: string | number) {
while (typeof x === "string") {
if (cond) continue;
x; // string
x = undefined;
}
x; // number
}
function c(x: string | number) {
while (typeof x === "string") {
if (cond) break;
x; // string
x = undefined;
}
x; // string | number
}
//// [typeGuardsInWhileStatement.js]
var cond;
function a(x) {
while (typeof x === "string") {
x; // string
x = undefined;
}
x; // number
}
function b(x) {
while (typeof x === "string") {
if (cond)
continue;
x; // string
x = undefined;
}
x; // number
}
function c(x) {
while (typeof x === "string") {
if (cond)
break;
x; // string
x = undefined;
}
x; // string | number
}
@@ -0,0 +1,62 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInWhileStatement.ts ===
let cond: boolean;
>cond : Symbol(cond, Decl(typeGuardsInWhileStatement.ts, 0, 3))
function a(x: string | number) {
>a : Symbol(a, Decl(typeGuardsInWhileStatement.ts, 0, 18))
>x : Symbol(x, Decl(typeGuardsInWhileStatement.ts, 1, 11))
while (typeof x === "string") {
>x : Symbol(x, Decl(typeGuardsInWhileStatement.ts, 1, 11))
x; // string
>x : Symbol(x, Decl(typeGuardsInWhileStatement.ts, 1, 11))
x = undefined;
>x : Symbol(x, Decl(typeGuardsInWhileStatement.ts, 1, 11))
>undefined : Symbol(undefined)
}
x; // number
>x : Symbol(x, Decl(typeGuardsInWhileStatement.ts, 1, 11))
}
function b(x: string | number) {
>b : Symbol(b, Decl(typeGuardsInWhileStatement.ts, 7, 1))
>x : Symbol(x, Decl(typeGuardsInWhileStatement.ts, 8, 11))
while (typeof x === "string") {
>x : Symbol(x, Decl(typeGuardsInWhileStatement.ts, 8, 11))
if (cond) continue;
>cond : Symbol(cond, Decl(typeGuardsInWhileStatement.ts, 0, 3))
x; // string
>x : Symbol(x, Decl(typeGuardsInWhileStatement.ts, 8, 11))
x = undefined;
>x : Symbol(x, Decl(typeGuardsInWhileStatement.ts, 8, 11))
>undefined : Symbol(undefined)
}
x; // number
>x : Symbol(x, Decl(typeGuardsInWhileStatement.ts, 8, 11))
}
function c(x: string | number) {
>c : Symbol(c, Decl(typeGuardsInWhileStatement.ts, 15, 1))
>x : Symbol(x, Decl(typeGuardsInWhileStatement.ts, 16, 11))
while (typeof x === "string") {
>x : Symbol(x, Decl(typeGuardsInWhileStatement.ts, 16, 11))
if (cond) break;
>cond : Symbol(cond, Decl(typeGuardsInWhileStatement.ts, 0, 3))
x; // string
>x : Symbol(x, Decl(typeGuardsInWhileStatement.ts, 16, 11))
x = undefined;
>x : Symbol(x, Decl(typeGuardsInWhileStatement.ts, 16, 11))
>undefined : Symbol(undefined)
}
x; // string | number
>x : Symbol(x, Decl(typeGuardsInWhileStatement.ts, 16, 11))
}
@@ -0,0 +1,74 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInWhileStatement.ts ===
let cond: boolean;
>cond : boolean
function a(x: string | number) {
>a : (x: string | number) => void
>x : string | number
while (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
>"string" : string
x; // string
>x : string
x = undefined;
>x = undefined : undefined
>x : string | number
>undefined : undefined
}
x; // number
>x : number
}
function b(x: string | number) {
>b : (x: string | number) => void
>x : string | number
while (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
>"string" : string
if (cond) continue;
>cond : boolean
x; // string
>x : string
x = undefined;
>x = undefined : undefined
>x : string | number
>undefined : undefined
}
x; // number
>x : number
}
function c(x: string | number) {
>c : (x: string | number) => void
>x : string | number
while (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
>"string" : string
if (cond) break;
>cond : boolean
x; // string
>x : string
x = undefined;
>x = undefined : undefined
>x : string | number
>undefined : undefined
}
x; // string | number
>x : number | string
}
@@ -24,9 +24,9 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTyp
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(43,1): error TS2322: Type 'string' is not assignable to type 'number'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(64,5): error TS2322: Type 'U' is not assignable to type 'T'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(65,5): error TS2322: Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(69,5): error TS2322: Type 'T | U' is not assignable to type 'T'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(70,5): error TS2322: Type 'T | U' is not assignable to type 'T'.
Type 'U' is not assignable to type 'T'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(70,5): error TS2322: Type 'T | U' is not assignable to type 'U'.
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTypesAssignability.ts(71,5): error TS2322: Type 'T | U' is not assignable to type 'U'.
Type 'T' is not assignable to type 'U'.
@@ -142,6 +142,7 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/unionTyp
var x : T | U;
x = t; // ok
x = u; // ok
x = undefined;
t = x; // error U not assignable to T
~
!!! error TS2322: Type 'T | U' is not assignable to type 'T'.
@@ -67,6 +67,7 @@ function foo<T, U>(t: T, u: U) {
var x : T | U;
x = t; // ok
x = u; // ok
x = undefined;
t = x; // error U not assignable to T
u = x; // error T not assignable to U
}
@@ -157,6 +158,7 @@ function foo(t, u) {
var x;
x = t; // ok
x = u; // ok
x = undefined;
t = x; // error U not assignable to T
u = x; // error T not assignable to U
}