Merge pull request #1077 from Microsoft/typeGuardConformance

Type guard conformance
This commit is contained in:
Sheetal Nandi
2014-11-12 13:09:09 -08:00
75 changed files with 9214 additions and 0 deletions

View File

@@ -0,0 +1,97 @@
//// [typeGuardOfFormExpr1AndExpr2.ts]
var str: string;
var bool: boolean;
var num: number;
var strOrNum: string | number;
var strOrNumOrBool: string | number | boolean;
var numOrBool: number | boolean;
class C { private p; }
var c: C;
var cOrBool: C| boolean;
var strOrNumOrBoolOrC: string | number | boolean | C;
// A type guard of the form expr1 && expr2
// - when true, narrows the type of x by expr1 when true and then by expr2 when true, or
// - when false, narrows the type of x to T1 | T2, where T1 is the type of x narrowed by expr1 when
// false, and T2 is the type of x narrowed by expr1 when true and then by expr2 when false.
// (typeguard1 && typeguard2)
if (typeof strOrNumOrBool !== "string" && typeof strOrNumOrBool !== "number") {
bool = strOrNumOrBool; // boolean
}
else {
strOrNum = strOrNumOrBool; // string | number
}
// (typeguard1 && typeguard2 && typeguard3)
if (typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "number" && typeof strOrNumOrBoolOrC !== "boolean") {
c = strOrNumOrBoolOrC; // C
}
else {
strOrNumOrBool = strOrNumOrBoolOrC; // string | number | boolean
}
// (typeguard1 && typeguard2 && typeguard11(onAnotherType))
if (typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "number" && typeof strOrNumOrBool === "boolean") {
cOrBool = strOrNumOrBoolOrC; // C | boolean
bool = strOrNumOrBool; // boolean
}
else {
var r1: string | number | boolean | C = strOrNumOrBoolOrC; // string | number | boolean | C
var r2: string | number | boolean = strOrNumOrBool;
}
// (typeguard1) && simpleExpr
if (typeof strOrNumOrBool !== "string" && numOrBool !== strOrNumOrBool) {
numOrBool = strOrNumOrBool; // number | boolean
}
else {
var r3: string | number | boolean = strOrNumOrBool; // string | number | boolean
}
//// [typeGuardOfFormExpr1AndExpr2.js]
var str;
var bool;
var num;
var strOrNum;
var strOrNumOrBool;
var numOrBool;
var C = (function () {
function C() {
}
return C;
})();
var c;
var cOrBool;
var strOrNumOrBoolOrC;
// A type guard of the form expr1 && expr2
// - when true, narrows the type of x by expr1 when true and then by expr2 when true, or
// - when false, narrows the type of x to T1 | T2, where T1 is the type of x narrowed by expr1 when
// false, and T2 is the type of x narrowed by expr1 when true and then by expr2 when false.
// (typeguard1 && typeguard2)
if (typeof strOrNumOrBool !== "string" && typeof strOrNumOrBool !== "number") {
bool = strOrNumOrBool; // boolean
}
else {
strOrNum = strOrNumOrBool; // string | number
}
// (typeguard1 && typeguard2 && typeguard3)
if (typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "number" && typeof strOrNumOrBoolOrC !== "boolean") {
c = strOrNumOrBoolOrC; // C
}
else {
strOrNumOrBool = strOrNumOrBoolOrC; // string | number | boolean
}
// (typeguard1 && typeguard2 && typeguard11(onAnotherType))
if (typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "number" && typeof strOrNumOrBool === "boolean") {
cOrBool = strOrNumOrBoolOrC; // C | boolean
bool = strOrNumOrBool; // boolean
}
else {
var r1 = strOrNumOrBoolOrC; // string | number | boolean | C
var r2 = strOrNumOrBool;
}
// (typeguard1) && simpleExpr
if (typeof strOrNumOrBool !== "string" && numOrBool !== strOrNumOrBool) {
numOrBool = strOrNumOrBool; // number | boolean
}
else {
var r3 = strOrNumOrBool; // string | number | boolean
}

View File

@@ -0,0 +1,140 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormExpr1AndExpr2.ts ===
var str: string;
>str : string
var bool: boolean;
>bool : boolean
var num: number;
>num : number
var strOrNum: string | number;
>strOrNum : string | number
var strOrNumOrBool: string | number | boolean;
>strOrNumOrBool : string | number | boolean
var numOrBool: number | boolean;
>numOrBool : number | boolean
class C { private p; }
>C : C
>p : any
var c: C;
>c : C
>C : C
var cOrBool: C| boolean;
>cOrBool : boolean | C
>C : C
var strOrNumOrBoolOrC: string | number | boolean | C;
>strOrNumOrBoolOrC : string | number | boolean | C
>C : C
// A type guard of the form expr1 && expr2
// - when true, narrows the type of x by expr1 when true and then by expr2 when true, or
// - when false, narrows the type of x to T1 | T2, where T1 is the type of x narrowed by expr1 when
// false, and T2 is the type of x narrowed by expr1 when true and then by expr2 when false.
// (typeguard1 && typeguard2)
if (typeof strOrNumOrBool !== "string" && typeof strOrNumOrBool !== "number") {
>typeof strOrNumOrBool !== "string" && typeof strOrNumOrBool !== "number" : boolean
>typeof strOrNumOrBool !== "string" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : string | number | boolean
>typeof strOrNumOrBool !== "number" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : number | boolean
bool = strOrNumOrBool; // boolean
>bool = strOrNumOrBool : boolean
>bool : boolean
>strOrNumOrBool : boolean
}
else {
strOrNum = strOrNumOrBool; // string | number
>strOrNum = strOrNumOrBool : string | number
>strOrNum : string | number
>strOrNumOrBool : string | number
}
// (typeguard1 && typeguard2 && typeguard3)
if (typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "number" && typeof strOrNumOrBoolOrC !== "boolean") {
>typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "number" && typeof strOrNumOrBoolOrC !== "boolean" : boolean
>typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "number" : boolean
>typeof strOrNumOrBoolOrC !== "string" : boolean
>typeof strOrNumOrBoolOrC : string
>strOrNumOrBoolOrC : string | number | boolean | C
>typeof strOrNumOrBoolOrC !== "number" : boolean
>typeof strOrNumOrBoolOrC : string
>strOrNumOrBoolOrC : number | boolean | C
>typeof strOrNumOrBoolOrC !== "boolean" : boolean
>typeof strOrNumOrBoolOrC : string
>strOrNumOrBoolOrC : boolean | C
c = strOrNumOrBoolOrC; // C
>c = strOrNumOrBoolOrC : C
>c : C
>strOrNumOrBoolOrC : C
}
else {
strOrNumOrBool = strOrNumOrBoolOrC; // string | number | boolean
>strOrNumOrBool = strOrNumOrBoolOrC : string | number | boolean
>strOrNumOrBool : string | number | boolean
>strOrNumOrBoolOrC : string | number | boolean
}
// (typeguard1 && typeguard2 && typeguard11(onAnotherType))
if (typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "number" && typeof strOrNumOrBool === "boolean") {
>typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "number" && typeof strOrNumOrBool === "boolean" : boolean
>typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "number" : boolean
>typeof strOrNumOrBoolOrC !== "string" : boolean
>typeof strOrNumOrBoolOrC : string
>strOrNumOrBoolOrC : string | number | boolean | C
>typeof strOrNumOrBoolOrC !== "number" : boolean
>typeof strOrNumOrBoolOrC : string
>strOrNumOrBoolOrC : number | boolean | C
>typeof strOrNumOrBool === "boolean" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : string | number | boolean
cOrBool = strOrNumOrBoolOrC; // C | boolean
>cOrBool = strOrNumOrBoolOrC : boolean | C
>cOrBool : boolean | C
>strOrNumOrBoolOrC : boolean | C
bool = strOrNumOrBool; // boolean
>bool = strOrNumOrBool : boolean
>bool : boolean
>strOrNumOrBool : boolean
}
else {
var r1: string | number | boolean | C = strOrNumOrBoolOrC; // string | number | boolean | C
>r1 : string | number | boolean | C
>C : C
>strOrNumOrBoolOrC : string | number | boolean | C
var r2: string | number | boolean = strOrNumOrBool;
>r2 : string | number | boolean
>strOrNumOrBool : string | number | boolean
}
// (typeguard1) && simpleExpr
if (typeof strOrNumOrBool !== "string" && numOrBool !== strOrNumOrBool) {
>typeof strOrNumOrBool !== "string" && numOrBool !== strOrNumOrBool : boolean
>typeof strOrNumOrBool !== "string" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : string | number | boolean
>numOrBool !== strOrNumOrBool : boolean
>numOrBool : number | boolean
>strOrNumOrBool : number | boolean
numOrBool = strOrNumOrBool; // number | boolean
>numOrBool = strOrNumOrBool : number | boolean
>numOrBool : number | boolean
>strOrNumOrBool : number | boolean
}
else {
var r3: string | number | boolean = strOrNumOrBool; // string | number | boolean
>r3 : string | number | boolean
>strOrNumOrBool : string | number | boolean
}

View File

@@ -0,0 +1,97 @@
//// [typeGuardOfFormExpr1OrExpr2.ts]
var str: string;
var bool: boolean;
var num: number;
var strOrNum: string | number;
var strOrNumOrBool: string | number | boolean;
var numOrBool: number | boolean;
class C { private p; }
var c: C;
var cOrBool: C| boolean;
var strOrNumOrBoolOrC: string | number | boolean | C;
// A type guard of the form expr1 || expr2
// - when true, narrows the type of x to T1 | T2, where T1 is the type of x narrowed by expr1 when true,
// and T2 is the type of x narrowed by expr1 when false and then by expr2 when true, or
// - when false, narrows the type of x by expr1 when false and then by expr2 when false.
// (typeguard1 || typeguard2)
if (typeof strOrNumOrBool === "string" || typeof strOrNumOrBool === "number") {
strOrNum = strOrNumOrBool; // string | number
}
else {
bool = strOrNumOrBool; // boolean
}
// (typeguard1 || typeguard2 || typeguard3)
if (typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "number" || typeof strOrNumOrBoolOrC === "boolean") {
strOrNumOrBool = strOrNumOrBoolOrC; // string | number | boolean
}
else {
c = strOrNumOrBoolOrC; // C
}
// (typeguard1 || typeguard2 || typeguard11(onAnotherType))
if (typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "number" || typeof strOrNumOrBool !== "boolean") {
var r1: string | number | boolean | C = strOrNumOrBoolOrC; // string | number | boolean | C
var r2: string | number | boolean = strOrNumOrBool;
}
else {
cOrBool = strOrNumOrBoolOrC; // C | boolean
bool = strOrNumOrBool; // boolean
}
// (typeguard1) || simpleExpr
if (typeof strOrNumOrBool === "string" || numOrBool !== strOrNumOrBool) {
var r3: string | number | boolean = strOrNumOrBool; // string | number | boolean
}
else {
numOrBool = strOrNumOrBool; // number | boolean
}
//// [typeGuardOfFormExpr1OrExpr2.js]
var str;
var bool;
var num;
var strOrNum;
var strOrNumOrBool;
var numOrBool;
var C = (function () {
function C() {
}
return C;
})();
var c;
var cOrBool;
var strOrNumOrBoolOrC;
// A type guard of the form expr1 || expr2
// - when true, narrows the type of x to T1 | T2, where T1 is the type of x narrowed by expr1 when true,
// and T2 is the type of x narrowed by expr1 when false and then by expr2 when true, or
// - when false, narrows the type of x by expr1 when false and then by expr2 when false.
// (typeguard1 || typeguard2)
if (typeof strOrNumOrBool === "string" || typeof strOrNumOrBool === "number") {
strOrNum = strOrNumOrBool; // string | number
}
else {
bool = strOrNumOrBool; // boolean
}
// (typeguard1 || typeguard2 || typeguard3)
if (typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "number" || typeof strOrNumOrBoolOrC === "boolean") {
strOrNumOrBool = strOrNumOrBoolOrC; // string | number | boolean
}
else {
c = strOrNumOrBoolOrC; // C
}
// (typeguard1 || typeguard2 || typeguard11(onAnotherType))
if (typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "number" || typeof strOrNumOrBool !== "boolean") {
var r1 = strOrNumOrBoolOrC; // string | number | boolean | C
var r2 = strOrNumOrBool;
}
else {
cOrBool = strOrNumOrBoolOrC; // C | boolean
bool = strOrNumOrBool; // boolean
}
// (typeguard1) || simpleExpr
if (typeof strOrNumOrBool === "string" || numOrBool !== strOrNumOrBool) {
var r3 = strOrNumOrBool; // string | number | boolean
}
else {
numOrBool = strOrNumOrBool; // number | boolean
}

View File

@@ -0,0 +1,140 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormExpr1OrExpr2.ts ===
var str: string;
>str : string
var bool: boolean;
>bool : boolean
var num: number;
>num : number
var strOrNum: string | number;
>strOrNum : string | number
var strOrNumOrBool: string | number | boolean;
>strOrNumOrBool : string | number | boolean
var numOrBool: number | boolean;
>numOrBool : number | boolean
class C { private p; }
>C : C
>p : any
var c: C;
>c : C
>C : C
var cOrBool: C| boolean;
>cOrBool : boolean | C
>C : C
var strOrNumOrBoolOrC: string | number | boolean | C;
>strOrNumOrBoolOrC : string | number | boolean | C
>C : C
// A type guard of the form expr1 || expr2
// - when true, narrows the type of x to T1 | T2, where T1 is the type of x narrowed by expr1 when true,
// and T2 is the type of x narrowed by expr1 when false and then by expr2 when true, or
// - when false, narrows the type of x by expr1 when false and then by expr2 when false.
// (typeguard1 || typeguard2)
if (typeof strOrNumOrBool === "string" || typeof strOrNumOrBool === "number") {
>typeof strOrNumOrBool === "string" || typeof strOrNumOrBool === "number" : boolean
>typeof strOrNumOrBool === "string" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : string | number | boolean
>typeof strOrNumOrBool === "number" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : number | boolean
strOrNum = strOrNumOrBool; // string | number
>strOrNum = strOrNumOrBool : string | number
>strOrNum : string | number
>strOrNumOrBool : string | number
}
else {
bool = strOrNumOrBool; // boolean
>bool = strOrNumOrBool : boolean
>bool : boolean
>strOrNumOrBool : boolean
}
// (typeguard1 || typeguard2 || typeguard3)
if (typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "number" || typeof strOrNumOrBoolOrC === "boolean") {
>typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "number" || typeof strOrNumOrBoolOrC === "boolean" : boolean
>typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "number" : boolean
>typeof strOrNumOrBoolOrC === "string" : boolean
>typeof strOrNumOrBoolOrC : string
>strOrNumOrBoolOrC : string | number | boolean | C
>typeof strOrNumOrBoolOrC === "number" : boolean
>typeof strOrNumOrBoolOrC : string
>strOrNumOrBoolOrC : number | boolean | C
>typeof strOrNumOrBoolOrC === "boolean" : boolean
>typeof strOrNumOrBoolOrC : string
>strOrNumOrBoolOrC : boolean | C
strOrNumOrBool = strOrNumOrBoolOrC; // string | number | boolean
>strOrNumOrBool = strOrNumOrBoolOrC : string | number | boolean
>strOrNumOrBool : string | number | boolean
>strOrNumOrBoolOrC : string | number | boolean
}
else {
c = strOrNumOrBoolOrC; // C
>c = strOrNumOrBoolOrC : C
>c : C
>strOrNumOrBoolOrC : C
}
// (typeguard1 || typeguard2 || typeguard11(onAnotherType))
if (typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "number" || typeof strOrNumOrBool !== "boolean") {
>typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "number" || typeof strOrNumOrBool !== "boolean" : boolean
>typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "number" : boolean
>typeof strOrNumOrBoolOrC === "string" : boolean
>typeof strOrNumOrBoolOrC : string
>strOrNumOrBoolOrC : string | number | boolean | C
>typeof strOrNumOrBoolOrC === "number" : boolean
>typeof strOrNumOrBoolOrC : string
>strOrNumOrBoolOrC : number | boolean | C
>typeof strOrNumOrBool !== "boolean" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : string | number | boolean
var r1: string | number | boolean | C = strOrNumOrBoolOrC; // string | number | boolean | C
>r1 : string | number | boolean | C
>C : C
>strOrNumOrBoolOrC : string | number | boolean | C
var r2: string | number | boolean = strOrNumOrBool;
>r2 : string | number | boolean
>strOrNumOrBool : string | number | boolean
}
else {
cOrBool = strOrNumOrBoolOrC; // C | boolean
>cOrBool = strOrNumOrBoolOrC : boolean | C
>cOrBool : boolean | C
>strOrNumOrBoolOrC : boolean | C
bool = strOrNumOrBool; // boolean
>bool = strOrNumOrBool : boolean
>bool : boolean
>strOrNumOrBool : boolean
}
// (typeguard1) || simpleExpr
if (typeof strOrNumOrBool === "string" || numOrBool !== strOrNumOrBool) {
>typeof strOrNumOrBool === "string" || numOrBool !== strOrNumOrBool : boolean
>typeof strOrNumOrBool === "string" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : string | number | boolean
>numOrBool !== strOrNumOrBool : boolean
>numOrBool : number | boolean
>strOrNumOrBool : number | boolean
var r3: string | number | boolean = strOrNumOrBool; // string | number | boolean
>r3 : string | number | boolean
>strOrNumOrBool : string | number | boolean
}
else {
numOrBool = strOrNumOrBool; // number | boolean
>numOrBool = strOrNumOrBool : number | boolean
>numOrBool : number | boolean
>strOrNumOrBool : number | boolean
}

View File

@@ -0,0 +1,74 @@
//// [typeGuardOfFormInstanceOf.ts]
// A type guard of the form x instanceof C, where C is of a subtype of the global type 'Function'
// and C has a property named 'prototype'
// - when true, narrows the type of x to the type of the 'prototype' property in C provided
// it is a subtype of the type of x, or
// - when false, has no effect on the type of x.
class C1 {
p1: string;
}
class C2 {
p2: number;
}
class D1 extends C1 {
p3: number;
}
var str: string;
var num: number;
var strOrNum: string | number;
var c1Orc2: C1 | C2;
str = c1Orc2 instanceof C1 && c1Orc2.p1; // C1
num = c1Orc2 instanceof C2 && c1Orc2.p2; // C2
str = c1Orc2 instanceof D1 && c1Orc2.p1; // D1
num = c1Orc2 instanceof D1 && c1Orc2.p3; // D1
var c2Ord1: C2 | D1;
num = c2Ord1 instanceof C2 && c2Ord1.p2; // C2
num = c2Ord1 instanceof D1 && c2Ord1.p3; // D1
str = c2Ord1 instanceof D1 && c2Ord1.p1; // D1
var r2: D1 | C2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1
//// [typeGuardOfFormInstanceOf.js]
// A type guard of the form x instanceof C, where C is of a subtype of the global type 'Function'
// and C has a property named 'prototype'
// - when true, narrows the type of x to the type of the 'prototype' property in C provided
// it is a subtype of the type of x, or
// - when false, has no effect on the type of x.
var __extends = this.__extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
var C1 = (function () {
function C1() {
}
return C1;
})();
var C2 = (function () {
function C2() {
}
return C2;
})();
var D1 = (function (_super) {
__extends(D1, _super);
function D1() {
_super.apply(this, arguments);
}
return D1;
})(C1);
var str;
var num;
var strOrNum;
var c1Orc2;
str = c1Orc2 instanceof C1 && c1Orc2.p1; // C1
num = c1Orc2 instanceof C2 && c1Orc2.p2; // C2
str = c1Orc2 instanceof D1 && c1Orc2.p1; // D1
num = c1Orc2 instanceof D1 && c1Orc2.p3; // D1
var c2Ord1;
num = c2Ord1 instanceof C2 && c2Ord1.p2; // C2
num = c2Ord1 instanceof D1 && c2Ord1.p3; // D1
str = c2Ord1 instanceof D1 && c2Ord1.p1; // D1
var r2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1

View File

@@ -0,0 +1,132 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormInstanceOf.ts ===
// A type guard of the form x instanceof C, where C is of a subtype of the global type 'Function'
// and C has a property named 'prototype'
// - when true, narrows the type of x to the type of the 'prototype' property in C provided
// it is a subtype of the type of x, or
// - when false, has no effect on the type of x.
class C1 {
>C1 : C1
p1: string;
>p1 : string
}
class C2 {
>C2 : C2
p2: number;
>p2 : number
}
class D1 extends C1 {
>D1 : D1
>C1 : C1
p3: number;
>p3 : number
}
var str: string;
>str : string
var num: number;
>num : number
var strOrNum: string | number;
>strOrNum : string | number
var c1Orc2: C1 | C2;
>c1Orc2 : C1 | C2
>C1 : C1
>C2 : C2
str = c1Orc2 instanceof C1 && c1Orc2.p1; // C1
>str = c1Orc2 instanceof C1 && c1Orc2.p1 : string
>str : string
>c1Orc2 instanceof C1 && c1Orc2.p1 : string
>c1Orc2 instanceof C1 : boolean
>c1Orc2 : C1 | C2
>C1 : typeof C1
>c1Orc2.p1 : string
>c1Orc2 : C1
>p1 : string
num = c1Orc2 instanceof C2 && c1Orc2.p2; // C2
>num = c1Orc2 instanceof C2 && c1Orc2.p2 : number
>num : number
>c1Orc2 instanceof C2 && c1Orc2.p2 : number
>c1Orc2 instanceof C2 : boolean
>c1Orc2 : C1 | C2
>C2 : typeof C2
>c1Orc2.p2 : number
>c1Orc2 : C2
>p2 : number
str = c1Orc2 instanceof D1 && c1Orc2.p1; // D1
>str = c1Orc2 instanceof D1 && c1Orc2.p1 : string
>str : string
>c1Orc2 instanceof D1 && c1Orc2.p1 : string
>c1Orc2 instanceof D1 : boolean
>c1Orc2 : C1 | C2
>D1 : typeof D1
>c1Orc2.p1 : string
>c1Orc2 : D1
>p1 : string
num = c1Orc2 instanceof D1 && c1Orc2.p3; // D1
>num = c1Orc2 instanceof D1 && c1Orc2.p3 : number
>num : number
>c1Orc2 instanceof D1 && c1Orc2.p3 : number
>c1Orc2 instanceof D1 : boolean
>c1Orc2 : C1 | C2
>D1 : typeof D1
>c1Orc2.p3 : number
>c1Orc2 : D1
>p3 : number
var c2Ord1: C2 | D1;
>c2Ord1 : C2 | D1
>C2 : C2
>D1 : D1
num = c2Ord1 instanceof C2 && c2Ord1.p2; // C2
>num = c2Ord1 instanceof C2 && c2Ord1.p2 : number
>num : number
>c2Ord1 instanceof C2 && c2Ord1.p2 : number
>c2Ord1 instanceof C2 : boolean
>c2Ord1 : C2 | D1
>C2 : typeof C2
>c2Ord1.p2 : number
>c2Ord1 : C2
>p2 : number
num = c2Ord1 instanceof D1 && c2Ord1.p3; // D1
>num = c2Ord1 instanceof D1 && c2Ord1.p3 : number
>num : number
>c2Ord1 instanceof D1 && c2Ord1.p3 : number
>c2Ord1 instanceof D1 : boolean
>c2Ord1 : C2 | D1
>D1 : typeof D1
>c2Ord1.p3 : number
>c2Ord1 : D1
>p3 : number
str = c2Ord1 instanceof D1 && c2Ord1.p1; // D1
>str = c2Ord1 instanceof D1 && c2Ord1.p1 : string
>str : string
>c2Ord1 instanceof D1 && c2Ord1.p1 : string
>c2Ord1 instanceof D1 : boolean
>c2Ord1 : C2 | D1
>D1 : typeof D1
>c2Ord1.p1 : string
>c2Ord1 : D1
>p1 : string
var r2: D1 | C2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1
>r2 : C2 | D1
>D1 : D1
>C2 : C2
>c2Ord1 instanceof C1 && c2Ord1 : C2 | D1
>c2Ord1 instanceof C1 : boolean
>c2Ord1 : C2 | D1
>C1 : typeof C1
>c2Ord1 : C2 | D1

View File

@@ -0,0 +1,62 @@
//// [typeGuardOfFormInstanceOfOnInterface.ts]
// A type guard of the form x instanceof C, where C is of a subtype of the global type 'Function'
// and C has a property named 'prototype'
// - when true, narrows the type of x to the type of the 'prototype' property in C provided
// it is a subtype of the type of x, or
// - when false, has no effect on the type of x.
interface C1 {
(): C1;
prototype: C1;
p1: string;
}
interface C2 {
(): C2;
prototype: C2;
p2: number;
}
interface D1 extends C1 {
prototype: D1;
p3: number;
}
var str: string;
var num: number;
var strOrNum: string | number;
var c1: C1;
var c2: C2;
var d1: D1;
var c1Orc2: C1 | C2;
str = c1Orc2 instanceof c1 && c1Orc2.p1; // C1
num = c1Orc2 instanceof c2 && c1Orc2.p2; // C2
str = c1Orc2 instanceof d1 && c1Orc2.p1; // C1
num = c1Orc2 instanceof d1 && c1Orc2.p3; // D1
var c2Ord1: C2 | D1;
num = c2Ord1 instanceof c2 && c2Ord1.p2; // C2
num = c2Ord1 instanceof d1 && c2Ord1.p3; // D1
str = c2Ord1 instanceof d1 && c2Ord1.p1; // D1
var r2: D1 | C2 = c2Ord1 instanceof c1 && c2Ord1; // C2 | D1
//// [typeGuardOfFormInstanceOfOnInterface.js]
// A type guard of the form x instanceof C, where C is of a subtype of the global type 'Function'
// and C has a property named 'prototype'
// - when true, narrows the type of x to the type of the 'prototype' property in C provided
// it is a subtype of the type of x, or
// - when false, has no effect on the type of x.
var str;
var num;
var strOrNum;
var c1;
var c2;
var d1;
var c1Orc2;
str = c1Orc2 instanceof c1 && c1Orc2.p1; // C1
num = c1Orc2 instanceof c2 && c1Orc2.p2; // C2
str = c1Orc2 instanceof d1 && c1Orc2.p1; // C1
num = c1Orc2 instanceof d1 && c1Orc2.p3; // D1
var c2Ord1;
num = c2Ord1 instanceof c2 && c2Ord1.p2; // C2
num = c2Ord1 instanceof d1 && c2Ord1.p3; // D1
str = c2Ord1 instanceof d1 && c2Ord1.p1; // D1
var r2 = c2Ord1 instanceof c1 && c2Ord1; // C2 | D1

View File

@@ -0,0 +1,162 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormInstanceOfOnInterface.ts ===
// A type guard of the form x instanceof C, where C is of a subtype of the global type 'Function'
// and C has a property named 'prototype'
// - when true, narrows the type of x to the type of the 'prototype' property in C provided
// it is a subtype of the type of x, or
// - when false, has no effect on the type of x.
interface C1 {
>C1 : C1
(): C1;
>C1 : C1
prototype: C1;
>prototype : C1
>C1 : C1
p1: string;
>p1 : string
}
interface C2 {
>C2 : C2
(): C2;
>C2 : C2
prototype: C2;
>prototype : C2
>C2 : C2
p2: number;
>p2 : number
}
interface D1 extends C1 {
>D1 : D1
>C1 : C1
prototype: D1;
>prototype : D1
>D1 : D1
p3: number;
>p3 : number
}
var str: string;
>str : string
var num: number;
>num : number
var strOrNum: string | number;
>strOrNum : string | number
var c1: C1;
>c1 : C1
>C1 : C1
var c2: C2;
>c2 : C2
>C2 : C2
var d1: D1;
>d1 : D1
>D1 : D1
var c1Orc2: C1 | C2;
>c1Orc2 : C1 | C2
>C1 : C1
>C2 : C2
str = c1Orc2 instanceof c1 && c1Orc2.p1; // C1
>str = c1Orc2 instanceof c1 && c1Orc2.p1 : string
>str : string
>c1Orc2 instanceof c1 && c1Orc2.p1 : string
>c1Orc2 instanceof c1 : boolean
>c1Orc2 : C1 | C2
>c1 : C1
>c1Orc2.p1 : string
>c1Orc2 : C1
>p1 : string
num = c1Orc2 instanceof c2 && c1Orc2.p2; // C2
>num = c1Orc2 instanceof c2 && c1Orc2.p2 : number
>num : number
>c1Orc2 instanceof c2 && c1Orc2.p2 : number
>c1Orc2 instanceof c2 : boolean
>c1Orc2 : C1 | C2
>c2 : C2
>c1Orc2.p2 : number
>c1Orc2 : C2
>p2 : number
str = c1Orc2 instanceof d1 && c1Orc2.p1; // C1
>str = c1Orc2 instanceof d1 && c1Orc2.p1 : string
>str : string
>c1Orc2 instanceof d1 && c1Orc2.p1 : string
>c1Orc2 instanceof d1 : boolean
>c1Orc2 : C1 | C2
>d1 : D1
>c1Orc2.p1 : string
>c1Orc2 : D1
>p1 : string
num = c1Orc2 instanceof d1 && c1Orc2.p3; // D1
>num = c1Orc2 instanceof d1 && c1Orc2.p3 : number
>num : number
>c1Orc2 instanceof d1 && c1Orc2.p3 : number
>c1Orc2 instanceof d1 : boolean
>c1Orc2 : C1 | C2
>d1 : D1
>c1Orc2.p3 : number
>c1Orc2 : D1
>p3 : number
var c2Ord1: C2 | D1;
>c2Ord1 : C2 | D1
>C2 : C2
>D1 : D1
num = c2Ord1 instanceof c2 && c2Ord1.p2; // C2
>num = c2Ord1 instanceof c2 && c2Ord1.p2 : number
>num : number
>c2Ord1 instanceof c2 && c2Ord1.p2 : number
>c2Ord1 instanceof c2 : boolean
>c2Ord1 : C2 | D1
>c2 : C2
>c2Ord1.p2 : number
>c2Ord1 : C2
>p2 : number
num = c2Ord1 instanceof d1 && c2Ord1.p3; // D1
>num = c2Ord1 instanceof d1 && c2Ord1.p3 : number
>num : number
>c2Ord1 instanceof d1 && c2Ord1.p3 : number
>c2Ord1 instanceof d1 : boolean
>c2Ord1 : C2 | D1
>d1 : D1
>c2Ord1.p3 : number
>c2Ord1 : D1
>p3 : number
str = c2Ord1 instanceof d1 && c2Ord1.p1; // D1
>str = c2Ord1 instanceof d1 && c2Ord1.p1 : string
>str : string
>c2Ord1 instanceof d1 && c2Ord1.p1 : string
>c2Ord1 instanceof d1 : boolean
>c2Ord1 : C2 | D1
>d1 : D1
>c2Ord1.p1 : string
>c2Ord1 : D1
>p1 : string
var r2: D1 | C2 = c2Ord1 instanceof c1 && c2Ord1; // C2 | D1
>r2 : C2 | D1
>D1 : D1
>C2 : C2
>c2Ord1 instanceof c1 && c2Ord1 : C2 | D1
>c2Ord1 instanceof c1 : boolean
>c2Ord1 : C2 | D1
>c1 : C1
>c2Ord1 : C2 | D1

View File

@@ -0,0 +1,107 @@
//// [typeGuardOfFormNotExpr.ts]
var str: string;
var bool: boolean;
var num: number;
var strOrNum: string | number;
var strOrNumOrBool: string | number | boolean;
var numOrBool: number | boolean;
// A type guard of the form !expr
// - when true, narrows the type of x by expr when false, or
// - when false, narrows the type of x by expr when true.
// !typeguard1
if (!(typeof strOrNum === "string")) {
num === strOrNum; // number
}
else {
str = strOrNum; // string
}
// !(typeguard1 || typeguard2)
if (!(typeof strOrNumOrBool === "string" || typeof strOrNumOrBool === "number")) {
bool = strOrNumOrBool; // boolean
}
else {
strOrNum = strOrNumOrBool; // string | number
}
// !(typeguard1) || !(typeguard2)
if (!(typeof strOrNumOrBool !== "string") || !(typeof strOrNumOrBool !== "number")) {
strOrNum = strOrNumOrBool; // string | number
}
else {
bool = strOrNumOrBool; // boolean
}
// !(typeguard1 && typeguard2)
if (!(typeof strOrNumOrBool !== "string" && typeof strOrNumOrBool !== "number")) {
strOrNum = strOrNumOrBool; // string | number
}
else {
bool = strOrNumOrBool; // boolean
}
// !(typeguard1) && !(typeguard2)
if (!(typeof strOrNumOrBool === "string") && !(typeof strOrNumOrBool === "number")) {
bool = strOrNumOrBool; // boolean
}
else {
strOrNum = strOrNumOrBool; // string | number
}
// !(typeguard1) && simpleExpr
if (!(typeof strOrNumOrBool === "string") && numOrBool !== strOrNumOrBool) {
numOrBool = strOrNumOrBool; // number | boolean
}
else {
var r1: string | number | boolean = strOrNumOrBool; // string | number | boolean
}
//// [typeGuardOfFormNotExpr.js]
var str;
var bool;
var num;
var strOrNum;
var strOrNumOrBool;
var numOrBool;
// A type guard of the form !expr
// - when true, narrows the type of x by expr when false, or
// - when false, narrows the type of x by expr when true.
// !typeguard1
if (!(typeof strOrNum === "string")) {
num === strOrNum; // number
}
else {
str = strOrNum; // string
}
// !(typeguard1 || typeguard2)
if (!(typeof strOrNumOrBool === "string" || typeof strOrNumOrBool === "number")) {
bool = strOrNumOrBool; // boolean
}
else {
strOrNum = strOrNumOrBool; // string | number
}
// !(typeguard1) || !(typeguard2)
if (!(typeof strOrNumOrBool !== "string") || !(typeof strOrNumOrBool !== "number")) {
strOrNum = strOrNumOrBool; // string | number
}
else {
bool = strOrNumOrBool; // boolean
}
// !(typeguard1 && typeguard2)
if (!(typeof strOrNumOrBool !== "string" && typeof strOrNumOrBool !== "number")) {
strOrNum = strOrNumOrBool; // string | number
}
else {
bool = strOrNumOrBool; // boolean
}
// !(typeguard1) && !(typeguard2)
if (!(typeof strOrNumOrBool === "string") && !(typeof strOrNumOrBool === "number")) {
bool = strOrNumOrBool; // boolean
}
else {
strOrNum = strOrNumOrBool; // string | number
}
// !(typeguard1) && simpleExpr
if (!(typeof strOrNumOrBool === "string") && numOrBool !== strOrNumOrBool) {
numOrBool = strOrNumOrBool; // number | boolean
}
else {
var r1 = strOrNumOrBool; // string | number | boolean
}

View File

@@ -0,0 +1,160 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormNotExpr.ts ===
var str: string;
>str : string
var bool: boolean;
>bool : boolean
var num: number;
>num : number
var strOrNum: string | number;
>strOrNum : string | number
var strOrNumOrBool: string | number | boolean;
>strOrNumOrBool : string | number | boolean
var numOrBool: number | boolean;
>numOrBool : number | boolean
// A type guard of the form !expr
// - when true, narrows the type of x by expr when false, or
// - when false, narrows the type of x by expr when true.
// !typeguard1
if (!(typeof strOrNum === "string")) {
>!(typeof strOrNum === "string") : boolean
>(typeof strOrNum === "string") : boolean
>typeof strOrNum === "string" : boolean
>typeof strOrNum : string
>strOrNum : string | number
num === strOrNum; // number
>num === strOrNum : boolean
>num : number
>strOrNum : number
}
else {
str = strOrNum; // string
>str = strOrNum : string
>str : string
>strOrNum : string
}
// !(typeguard1 || typeguard2)
if (!(typeof strOrNumOrBool === "string" || typeof strOrNumOrBool === "number")) {
>!(typeof strOrNumOrBool === "string" || typeof strOrNumOrBool === "number") : boolean
>(typeof strOrNumOrBool === "string" || typeof strOrNumOrBool === "number") : boolean
>typeof strOrNumOrBool === "string" || typeof strOrNumOrBool === "number" : boolean
>typeof strOrNumOrBool === "string" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : string | number | boolean
>typeof strOrNumOrBool === "number" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : number | boolean
bool = strOrNumOrBool; // boolean
>bool = strOrNumOrBool : boolean
>bool : boolean
>strOrNumOrBool : boolean
}
else {
strOrNum = strOrNumOrBool; // string | number
>strOrNum = strOrNumOrBool : string | number
>strOrNum : string | number
>strOrNumOrBool : string | number
}
// !(typeguard1) || !(typeguard2)
if (!(typeof strOrNumOrBool !== "string") || !(typeof strOrNumOrBool !== "number")) {
>!(typeof strOrNumOrBool !== "string") || !(typeof strOrNumOrBool !== "number") : boolean
>!(typeof strOrNumOrBool !== "string") : boolean
>(typeof strOrNumOrBool !== "string") : boolean
>typeof strOrNumOrBool !== "string" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : string | number | boolean
>!(typeof strOrNumOrBool !== "number") : boolean
>(typeof strOrNumOrBool !== "number") : boolean
>typeof strOrNumOrBool !== "number" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : number | boolean
strOrNum = strOrNumOrBool; // string | number
>strOrNum = strOrNumOrBool : string | number
>strOrNum : string | number
>strOrNumOrBool : string | number
}
else {
bool = strOrNumOrBool; // boolean
>bool = strOrNumOrBool : boolean
>bool : boolean
>strOrNumOrBool : boolean
}
// !(typeguard1 && typeguard2)
if (!(typeof strOrNumOrBool !== "string" && typeof strOrNumOrBool !== "number")) {
>!(typeof strOrNumOrBool !== "string" && typeof strOrNumOrBool !== "number") : boolean
>(typeof strOrNumOrBool !== "string" && typeof strOrNumOrBool !== "number") : boolean
>typeof strOrNumOrBool !== "string" && typeof strOrNumOrBool !== "number" : boolean
>typeof strOrNumOrBool !== "string" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : string | number | boolean
>typeof strOrNumOrBool !== "number" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : number | boolean
strOrNum = strOrNumOrBool; // string | number
>strOrNum = strOrNumOrBool : string | number
>strOrNum : string | number
>strOrNumOrBool : string | number
}
else {
bool = strOrNumOrBool; // boolean
>bool = strOrNumOrBool : boolean
>bool : boolean
>strOrNumOrBool : boolean
}
// !(typeguard1) && !(typeguard2)
if (!(typeof strOrNumOrBool === "string") && !(typeof strOrNumOrBool === "number")) {
>!(typeof strOrNumOrBool === "string") && !(typeof strOrNumOrBool === "number") : boolean
>!(typeof strOrNumOrBool === "string") : boolean
>(typeof strOrNumOrBool === "string") : boolean
>typeof strOrNumOrBool === "string" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : string | number | boolean
>!(typeof strOrNumOrBool === "number") : boolean
>(typeof strOrNumOrBool === "number") : boolean
>typeof strOrNumOrBool === "number" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : number | boolean
bool = strOrNumOrBool; // boolean
>bool = strOrNumOrBool : boolean
>bool : boolean
>strOrNumOrBool : boolean
}
else {
strOrNum = strOrNumOrBool; // string | number
>strOrNum = strOrNumOrBool : string | number
>strOrNum : string | number
>strOrNumOrBool : string | number
}
// !(typeguard1) && simpleExpr
if (!(typeof strOrNumOrBool === "string") && numOrBool !== strOrNumOrBool) {
>!(typeof strOrNumOrBool === "string") && numOrBool !== strOrNumOrBool : boolean
>!(typeof strOrNumOrBool === "string") : boolean
>(typeof strOrNumOrBool === "string") : boolean
>typeof strOrNumOrBool === "string" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : string | number | boolean
>numOrBool !== strOrNumOrBool : boolean
>numOrBool : number | boolean
>strOrNumOrBool : number | boolean
numOrBool = strOrNumOrBool; // number | boolean
>numOrBool = strOrNumOrBool : number | boolean
>numOrBool : number | boolean
>strOrNumOrBool : number | boolean
}
else {
var r1: string | number | boolean = strOrNumOrBool; // string | number | boolean
>r1 : string | number | boolean
>strOrNumOrBool : string | number | boolean
}

View File

@@ -0,0 +1,169 @@
//// [typeGuardOfFormTypeOfBoolean.ts]
class C { private p: string };
var str: string;
var bool: boolean;
var num: number;
var strOrNum: string | number;
var strOrBool: string | boolean;
var numOrBool: number | boolean
var strOrNumOrBool: string | number | boolean;
var strOrC: string | C;
var numOrC: number | C;
var boolOrC: boolean | C;
var c: C;
// A type guard of the form typeof x === s,
// where s is a string literal with the value 'string', 'number', or 'boolean',
// - when true, narrows the type of x to the given primitive type, or
// - when false, removes the primitive type from the type of x.
if (typeof strOrNum === "boolean") {
bool = strOrNum; // boolean
}
else {
var z: string | number = strOrNum; // string | number
}
if (typeof strOrBool === "boolean") {
bool = strOrBool; // boolean
}
else {
str = strOrBool; // string
}
if (typeof numOrBool === "boolean") {
bool = numOrBool; // boolean
}
else {
num = numOrBool; // number
}
if (typeof strOrNumOrBool === "boolean") {
bool = strOrNumOrBool; // boolean
}
else {
strOrNum = strOrNumOrBool; // string | number
}
if (typeof boolOrC === "boolean") {
bool = boolOrC; // boolean
}
else {
c = boolOrC; // C
}
// A type guard of the form typeof x !== s, where s is a string literal,
// - when true, narrows the type of x by typeof x === s when false, or
// - when false, narrows the type of x by typeof x === s when true.
if (typeof strOrNum !== "boolean") {
var z: string | number = strOrNum; // string | number
}
else {
bool = strOrNum; // boolean
}
if (typeof strOrBool !== "boolean") {
str = strOrBool; // string
}
else {
bool = strOrBool; // boolean
}
if (typeof numOrBool !== "boolean") {
num = numOrBool; // number
}
else {
bool = numOrBool; // boolean
}
if (typeof strOrNumOrBool !== "boolean") {
strOrNum = strOrNumOrBool; // string | number
}
else {
bool = strOrNumOrBool; // boolean
}
if (typeof boolOrC !== "boolean") {
c = boolOrC; // C
}
else {
bool = boolOrC; // boolean
}
//// [typeGuardOfFormTypeOfBoolean.js]
var C = (function () {
function C() {
}
return C;
})();
;
var str;
var bool;
var num;
var strOrNum;
var strOrBool;
var numOrBool;
var strOrNumOrBool;
var strOrC;
var numOrC;
var boolOrC;
var c;
// A type guard of the form typeof x === s,
// where s is a string literal with the value 'string', 'number', or 'boolean',
// - when true, narrows the type of x to the given primitive type, or
// - when false, removes the primitive type from the type of x.
if (typeof strOrNum === "boolean") {
bool = strOrNum; // boolean
}
else {
var z = strOrNum; // string | number
}
if (typeof strOrBool === "boolean") {
bool = strOrBool; // boolean
}
else {
str = strOrBool; // string
}
if (typeof numOrBool === "boolean") {
bool = numOrBool; // boolean
}
else {
num = numOrBool; // number
}
if (typeof strOrNumOrBool === "boolean") {
bool = strOrNumOrBool; // boolean
}
else {
strOrNum = strOrNumOrBool; // string | number
}
if (typeof boolOrC === "boolean") {
bool = boolOrC; // boolean
}
else {
c = boolOrC; // C
}
// A type guard of the form typeof x !== s, where s is a string literal,
// - when true, narrows the type of x by typeof x === s when false, or
// - when false, narrows the type of x by typeof x === s when true.
if (typeof strOrNum !== "boolean") {
var z = strOrNum; // string | number
}
else {
bool = strOrNum; // boolean
}
if (typeof strOrBool !== "boolean") {
str = strOrBool; // string
}
else {
bool = strOrBool; // boolean
}
if (typeof numOrBool !== "boolean") {
num = numOrBool; // number
}
else {
bool = numOrBool; // boolean
}
if (typeof strOrNumOrBool !== "boolean") {
strOrNum = strOrNumOrBool; // string | number
}
else {
bool = strOrNumOrBool; // boolean
}
if (typeof boolOrC !== "boolean") {
c = boolOrC; // C
}
else {
bool = boolOrC; // boolean
}

View File

@@ -0,0 +1,208 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfBoolean.ts ===
class C { private p: string };
>C : C
>p : string
var str: string;
>str : string
var bool: boolean;
>bool : boolean
var num: number;
>num : number
var strOrNum: string | number;
>strOrNum : string | number
var strOrBool: string | boolean;
>strOrBool : string | boolean
var numOrBool: number | boolean
>numOrBool : number | boolean
var strOrNumOrBool: string | number | boolean;
>strOrNumOrBool : string | number | boolean
var strOrC: string | C;
>strOrC : string | C
>C : C
var numOrC: number | C;
>numOrC : number | C
>C : C
var boolOrC: boolean | C;
>boolOrC : boolean | C
>C : C
var c: C;
>c : C
>C : C
// A type guard of the form typeof x === s,
// where s is a string literal with the value 'string', 'number', or 'boolean',
// - when true, narrows the type of x to the given primitive type, or
// - when false, removes the primitive type from the type of x.
if (typeof strOrNum === "boolean") {
>typeof strOrNum === "boolean" : boolean
>typeof strOrNum : string
>strOrNum : string | number
bool = strOrNum; // boolean
>bool = strOrNum : boolean
>bool : boolean
>strOrNum : boolean
}
else {
var z: string | number = strOrNum; // string | number
>z : string | number
>strOrNum : string | number
}
if (typeof strOrBool === "boolean") {
>typeof strOrBool === "boolean" : boolean
>typeof strOrBool : string
>strOrBool : string | boolean
bool = strOrBool; // boolean
>bool = strOrBool : boolean
>bool : boolean
>strOrBool : boolean
}
else {
str = strOrBool; // string
>str = strOrBool : string
>str : string
>strOrBool : string
}
if (typeof numOrBool === "boolean") {
>typeof numOrBool === "boolean" : boolean
>typeof numOrBool : string
>numOrBool : number | boolean
bool = numOrBool; // boolean
>bool = numOrBool : boolean
>bool : boolean
>numOrBool : boolean
}
else {
num = numOrBool; // number
>num = numOrBool : number
>num : number
>numOrBool : number
}
if (typeof strOrNumOrBool === "boolean") {
>typeof strOrNumOrBool === "boolean" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : string | number | boolean
bool = strOrNumOrBool; // boolean
>bool = strOrNumOrBool : boolean
>bool : boolean
>strOrNumOrBool : boolean
}
else {
strOrNum = strOrNumOrBool; // string | number
>strOrNum = strOrNumOrBool : string | number
>strOrNum : string | number
>strOrNumOrBool : string | number
}
if (typeof boolOrC === "boolean") {
>typeof boolOrC === "boolean" : boolean
>typeof boolOrC : string
>boolOrC : boolean | C
bool = boolOrC; // boolean
>bool = boolOrC : boolean
>bool : boolean
>boolOrC : boolean
}
else {
c = boolOrC; // C
>c = boolOrC : C
>c : C
>boolOrC : C
}
// A type guard of the form typeof x !== s, where s is a string literal,
// - when true, narrows the type of x by typeof x === s when false, or
// - when false, narrows the type of x by typeof x === s when true.
if (typeof strOrNum !== "boolean") {
>typeof strOrNum !== "boolean" : boolean
>typeof strOrNum : string
>strOrNum : string | number
var z: string | number = strOrNum; // string | number
>z : string | number
>strOrNum : string | number
}
else {
bool = strOrNum; // boolean
>bool = strOrNum : boolean
>bool : boolean
>strOrNum : boolean
}
if (typeof strOrBool !== "boolean") {
>typeof strOrBool !== "boolean" : boolean
>typeof strOrBool : string
>strOrBool : string | boolean
str = strOrBool; // string
>str = strOrBool : string
>str : string
>strOrBool : string
}
else {
bool = strOrBool; // boolean
>bool = strOrBool : boolean
>bool : boolean
>strOrBool : boolean
}
if (typeof numOrBool !== "boolean") {
>typeof numOrBool !== "boolean" : boolean
>typeof numOrBool : string
>numOrBool : number | boolean
num = numOrBool; // number
>num = numOrBool : number
>num : number
>numOrBool : number
}
else {
bool = numOrBool; // boolean
>bool = numOrBool : boolean
>bool : boolean
>numOrBool : boolean
}
if (typeof strOrNumOrBool !== "boolean") {
>typeof strOrNumOrBool !== "boolean" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : string | number | boolean
strOrNum = strOrNumOrBool; // string | number
>strOrNum = strOrNumOrBool : string | number
>strOrNum : string | number
>strOrNumOrBool : string | number
}
else {
bool = strOrNumOrBool; // boolean
>bool = strOrNumOrBool : boolean
>bool : boolean
>strOrNumOrBool : boolean
}
if (typeof boolOrC !== "boolean") {
>typeof boolOrC !== "boolean" : boolean
>typeof boolOrC : string
>boolOrC : boolean | C
c = boolOrC; // C
>c = boolOrC : C
>c : C
>boolOrC : C
}
else {
bool = boolOrC; // boolean
>bool = boolOrC : boolean
>bool : boolean
>boolOrC : boolean
}

View File

@@ -0,0 +1,73 @@
//// [typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts]
class C { private p: string };
var strOrNum: string | number;
var strOrBool: string | boolean;
var numOrBool: number | boolean
var strOrC: string | C;
// typeof x == s has not effect on typeguard
if (typeof strOrNum == "string") {
var r1 = strOrNum; // string | number
}
else {
var r1 = strOrNum; // string | number
}
if (typeof strOrBool == "boolean") {
var r2 = strOrBool; // string | boolean
}
else {
var r2 = strOrBool; // string | boolean
}
if (typeof numOrBool == "number") {
var r3 = numOrBool; // number | boolean
}
else {
var r3 = numOrBool; // number | boolean
}
if (typeof strOrC == "Object") {
var r4 = strOrC; // string | C
}
else {
var r4 = strOrC; // string | C
}
//// [typeGuardOfFormTypeOfEqualEqualHasNoEffect.js]
var C = (function () {
function C() {
}
return C;
})();
;
var strOrNum;
var strOrBool;
var numOrBool;
var strOrC;
// typeof x == s has not effect on typeguard
if (typeof strOrNum == "string") {
var r1 = strOrNum; // string | number
}
else {
var r1 = strOrNum; // string | number
}
if (typeof strOrBool == "boolean") {
var r2 = strOrBool; // string | boolean
}
else {
var r2 = strOrBool; // string | boolean
}
if (typeof numOrBool == "number") {
var r3 = numOrBool; // number | boolean
}
else {
var r3 = numOrBool; // number | boolean
}
if (typeof strOrC == "Object") {
var r4 = strOrC; // string | C
}
else {
var r4 = strOrC; // string | C
}

View File

@@ -0,0 +1,78 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts ===
class C { private p: string };
>C : C
>p : string
var strOrNum: string | number;
>strOrNum : string | number
var strOrBool: string | boolean;
>strOrBool : string | boolean
var numOrBool: number | boolean
>numOrBool : number | boolean
var strOrC: string | C;
>strOrC : string | C
>C : C
// typeof x == s has not effect on typeguard
if (typeof strOrNum == "string") {
>typeof strOrNum == "string" : boolean
>typeof strOrNum : string
>strOrNum : string | number
var r1 = strOrNum; // string | number
>r1 : string | number
>strOrNum : string | number
}
else {
var r1 = strOrNum; // string | number
>r1 : string | number
>strOrNum : string | number
}
if (typeof strOrBool == "boolean") {
>typeof strOrBool == "boolean" : boolean
>typeof strOrBool : string
>strOrBool : string | boolean
var r2 = strOrBool; // string | boolean
>r2 : string | boolean
>strOrBool : string | boolean
}
else {
var r2 = strOrBool; // string | boolean
>r2 : string | boolean
>strOrBool : string | boolean
}
if (typeof numOrBool == "number") {
>typeof numOrBool == "number" : boolean
>typeof numOrBool : string
>numOrBool : number | boolean
var r3 = numOrBool; // number | boolean
>r3 : number | boolean
>numOrBool : number | boolean
}
else {
var r3 = numOrBool; // number | boolean
>r3 : number | boolean
>numOrBool : number | boolean
}
if (typeof strOrC == "Object") {
>typeof strOrC == "Object" : boolean
>typeof strOrC : string
>strOrC : string | C
var r4 = strOrC; // string | C
>r4 : string | C
>strOrC : string | C
}
else {
var r4 = strOrC; // string | C
>r4 : string | C
>strOrC : string | C
}

View File

@@ -0,0 +1,73 @@
//// [typeGuardOfFormTypeOfNotEqualHasNoEffect.ts]
class C { private p: string };
var strOrNum: string | number;
var strOrBool: string | boolean;
var numOrBool: number | boolean
var strOrC: string | C;
// typeof x != s has not effect on typeguard
if (typeof strOrNum != "string") {
var r1 = strOrNum; // string | number
}
else {
var r1 = strOrNum; // string | number
}
if (typeof strOrBool != "boolean") {
var r2 = strOrBool; // string | boolean
}
else {
var r2 = strOrBool; // string | boolean
}
if (typeof numOrBool != "number") {
var r3 = numOrBool; // number | boolean
}
else {
var r3 = numOrBool; // number | boolean
}
if (typeof strOrC != "Object") {
var r4 = strOrC; // string | C
}
else {
var r4 = strOrC; // string | C
}
//// [typeGuardOfFormTypeOfNotEqualHasNoEffect.js]
var C = (function () {
function C() {
}
return C;
})();
;
var strOrNum;
var strOrBool;
var numOrBool;
var strOrC;
// typeof x != s has not effect on typeguard
if (typeof strOrNum != "string") {
var r1 = strOrNum; // string | number
}
else {
var r1 = strOrNum; // string | number
}
if (typeof strOrBool != "boolean") {
var r2 = strOrBool; // string | boolean
}
else {
var r2 = strOrBool; // string | boolean
}
if (typeof numOrBool != "number") {
var r3 = numOrBool; // number | boolean
}
else {
var r3 = numOrBool; // number | boolean
}
if (typeof strOrC != "Object") {
var r4 = strOrC; // string | C
}
else {
var r4 = strOrC; // string | C
}

View File

@@ -0,0 +1,78 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts ===
class C { private p: string };
>C : C
>p : string
var strOrNum: string | number;
>strOrNum : string | number
var strOrBool: string | boolean;
>strOrBool : string | boolean
var numOrBool: number | boolean
>numOrBool : number | boolean
var strOrC: string | C;
>strOrC : string | C
>C : C
// typeof x != s has not effect on typeguard
if (typeof strOrNum != "string") {
>typeof strOrNum != "string" : boolean
>typeof strOrNum : string
>strOrNum : string | number
var r1 = strOrNum; // string | number
>r1 : string | number
>strOrNum : string | number
}
else {
var r1 = strOrNum; // string | number
>r1 : string | number
>strOrNum : string | number
}
if (typeof strOrBool != "boolean") {
>typeof strOrBool != "boolean" : boolean
>typeof strOrBool : string
>strOrBool : string | boolean
var r2 = strOrBool; // string | boolean
>r2 : string | boolean
>strOrBool : string | boolean
}
else {
var r2 = strOrBool; // string | boolean
>r2 : string | boolean
>strOrBool : string | boolean
}
if (typeof numOrBool != "number") {
>typeof numOrBool != "number" : boolean
>typeof numOrBool : string
>numOrBool : number | boolean
var r3 = numOrBool; // number | boolean
>r3 : number | boolean
>numOrBool : number | boolean
}
else {
var r3 = numOrBool; // number | boolean
>r3 : number | boolean
>numOrBool : number | boolean
}
if (typeof strOrC != "Object") {
>typeof strOrC != "Object" : boolean
>typeof strOrC : string
>strOrC : string | C
var r4 = strOrC; // string | C
>r4 : string | C
>strOrC : string | C
}
else {
var r4 = strOrC; // string | C
>r4 : string | C
>strOrC : string | C
}

View File

@@ -0,0 +1,169 @@
//// [typeGuardOfFormTypeOfNumber.ts]
class C { private p: string };
var str: string;
var bool: boolean;
var num: number;
var strOrNum: string | number;
var strOrBool: string | boolean;
var numOrBool: number | boolean
var strOrNumOrBool: string | number | boolean;
var strOrC: string | C;
var numOrC: number | C;
var boolOrC: boolean | C;
var c: C;
// A type guard of the form typeof x === s,
// where s is a string literal with the value 'string', 'number', or 'boolean',
// - when true, narrows the type of x to the given primitive type, or
// - when false, removes the primitive type from the type of x.
if (typeof strOrNum === "number") {
num = strOrNum; // number
}
else {
str === strOrNum; // string
}
if (typeof strOrBool === "number") {
num = strOrBool; // number
}
else {
var y: string | boolean = strOrBool; // string | boolean
}
if (typeof numOrBool === "number") {
num = numOrBool; // number
}
else {
var x: number | boolean = numOrBool; // number | boolean
}
if (typeof strOrNumOrBool === "number") {
num = strOrNumOrBool; // number
}
else {
strOrBool = strOrNumOrBool; // string | boolean
}
if (typeof numOrC === "number") {
num = numOrC; // number
}
else {
c = numOrC; // C
}
// A type guard of the form typeof x !== s, where s is a string literal,
// - when true, narrows the type of x by typeof x === s when false, or
// - when false, narrows the type of x by typeof x === s when true.
if (typeof strOrNum !== "number") {
str === strOrNum; // string
}
else {
num = strOrNum; // number
}
if (typeof strOrBool !== "number") {
var y: string | boolean = strOrBool; // string | boolean
}
else {
num = strOrBool; // number
}
if (typeof numOrBool !== "number") {
var x: number | boolean = numOrBool; // number | boolean
}
else {
num = numOrBool; // number
}
if (typeof strOrNumOrBool !== "number") {
strOrBool = strOrNumOrBool; // string | boolean
}
else {
num = strOrNumOrBool; // number
}
if (typeof numOrC !== "number") {
c = numOrC; // C
}
else {
num = numOrC; // number
}
//// [typeGuardOfFormTypeOfNumber.js]
var C = (function () {
function C() {
}
return C;
})();
;
var str;
var bool;
var num;
var strOrNum;
var strOrBool;
var numOrBool;
var strOrNumOrBool;
var strOrC;
var numOrC;
var boolOrC;
var c;
// A type guard of the form typeof x === s,
// where s is a string literal with the value 'string', 'number', or 'boolean',
// - when true, narrows the type of x to the given primitive type, or
// - when false, removes the primitive type from the type of x.
if (typeof strOrNum === "number") {
num = strOrNum; // number
}
else {
str === strOrNum; // string
}
if (typeof strOrBool === "number") {
num = strOrBool; // number
}
else {
var y = strOrBool; // string | boolean
}
if (typeof numOrBool === "number") {
num = numOrBool; // number
}
else {
var x = numOrBool; // number | boolean
}
if (typeof strOrNumOrBool === "number") {
num = strOrNumOrBool; // number
}
else {
strOrBool = strOrNumOrBool; // string | boolean
}
if (typeof numOrC === "number") {
num = numOrC; // number
}
else {
c = numOrC; // C
}
// A type guard of the form typeof x !== s, where s is a string literal,
// - when true, narrows the type of x by typeof x === s when false, or
// - when false, narrows the type of x by typeof x === s when true.
if (typeof strOrNum !== "number") {
str === strOrNum; // string
}
else {
num = strOrNum; // number
}
if (typeof strOrBool !== "number") {
var y = strOrBool; // string | boolean
}
else {
num = strOrBool; // number
}
if (typeof numOrBool !== "number") {
var x = numOrBool; // number | boolean
}
else {
num = numOrBool; // number
}
if (typeof strOrNumOrBool !== "number") {
strOrBool = strOrNumOrBool; // string | boolean
}
else {
num = strOrNumOrBool; // number
}
if (typeof numOrC !== "number") {
c = numOrC; // C
}
else {
num = numOrC; // number
}

View File

@@ -0,0 +1,206 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNumber.ts ===
class C { private p: string };
>C : C
>p : string
var str: string;
>str : string
var bool: boolean;
>bool : boolean
var num: number;
>num : number
var strOrNum: string | number;
>strOrNum : string | number
var strOrBool: string | boolean;
>strOrBool : string | boolean
var numOrBool: number | boolean
>numOrBool : number | boolean
var strOrNumOrBool: string | number | boolean;
>strOrNumOrBool : string | number | boolean
var strOrC: string | C;
>strOrC : string | C
>C : C
var numOrC: number | C;
>numOrC : number | C
>C : C
var boolOrC: boolean | C;
>boolOrC : boolean | C
>C : C
var c: C;
>c : C
>C : C
// A type guard of the form typeof x === s,
// where s is a string literal with the value 'string', 'number', or 'boolean',
// - when true, narrows the type of x to the given primitive type, or
// - when false, removes the primitive type from the type of x.
if (typeof strOrNum === "number") {
>typeof strOrNum === "number" : boolean
>typeof strOrNum : string
>strOrNum : string | number
num = strOrNum; // number
>num = strOrNum : number
>num : number
>strOrNum : number
}
else {
str === strOrNum; // string
>str === strOrNum : boolean
>str : string
>strOrNum : string
}
if (typeof strOrBool === "number") {
>typeof strOrBool === "number" : boolean
>typeof strOrBool : string
>strOrBool : string | boolean
num = strOrBool; // number
>num = strOrBool : number
>num : number
>strOrBool : number
}
else {
var y: string | boolean = strOrBool; // string | boolean
>y : string | boolean
>strOrBool : string | boolean
}
if (typeof numOrBool === "number") {
>typeof numOrBool === "number" : boolean
>typeof numOrBool : string
>numOrBool : number | boolean
num = numOrBool; // number
>num = numOrBool : number
>num : number
>numOrBool : number
}
else {
var x: number | boolean = numOrBool; // number | boolean
>x : number | boolean
>numOrBool : boolean
}
if (typeof strOrNumOrBool === "number") {
>typeof strOrNumOrBool === "number" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : string | number | boolean
num = strOrNumOrBool; // number
>num = strOrNumOrBool : number
>num : number
>strOrNumOrBool : number
}
else {
strOrBool = strOrNumOrBool; // string | boolean
>strOrBool = strOrNumOrBool : string | boolean
>strOrBool : string | boolean
>strOrNumOrBool : string | boolean
}
if (typeof numOrC === "number") {
>typeof numOrC === "number" : boolean
>typeof numOrC : string
>numOrC : number | C
num = numOrC; // number
>num = numOrC : number
>num : number
>numOrC : number
}
else {
c = numOrC; // C
>c = numOrC : C
>c : C
>numOrC : C
}
// A type guard of the form typeof x !== s, where s is a string literal,
// - when true, narrows the type of x by typeof x === s when false, or
// - when false, narrows the type of x by typeof x === s when true.
if (typeof strOrNum !== "number") {
>typeof strOrNum !== "number" : boolean
>typeof strOrNum : string
>strOrNum : string | number
str === strOrNum; // string
>str === strOrNum : boolean
>str : string
>strOrNum : string
}
else {
num = strOrNum; // number
>num = strOrNum : number
>num : number
>strOrNum : number
}
if (typeof strOrBool !== "number") {
>typeof strOrBool !== "number" : boolean
>typeof strOrBool : string
>strOrBool : string | boolean
var y: string | boolean = strOrBool; // string | boolean
>y : string | boolean
>strOrBool : string | boolean
}
else {
num = strOrBool; // number
>num = strOrBool : number
>num : number
>strOrBool : number
}
if (typeof numOrBool !== "number") {
>typeof numOrBool !== "number" : boolean
>typeof numOrBool : string
>numOrBool : number | boolean
var x: number | boolean = numOrBool; // number | boolean
>x : number | boolean
>numOrBool : boolean
}
else {
num = numOrBool; // number
>num = numOrBool : number
>num : number
>numOrBool : number
}
if (typeof strOrNumOrBool !== "number") {
>typeof strOrNumOrBool !== "number" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : string | number | boolean
strOrBool = strOrNumOrBool; // string | boolean
>strOrBool = strOrNumOrBool : string | boolean
>strOrBool : string | boolean
>strOrNumOrBool : string | boolean
}
else {
num = strOrNumOrBool; // number
>num = strOrNumOrBool : number
>num : number
>strOrNumOrBool : number
}
if (typeof numOrC !== "number") {
>typeof numOrC !== "number" : boolean
>typeof numOrC : string
>numOrC : number | C
c = numOrC; // C
>c = numOrC : C
>c : C
>numOrC : C
}
else {
num = numOrC; // number
>num = numOrC : number
>num : number
>numOrC : number
}

View File

@@ -0,0 +1,148 @@
//// [typeGuardOfFormTypeOfOther.ts]
class C { private p: string };
var str: string;
var bool: boolean;
var num: number;
var strOrNum: string | number;
var strOrBool: string | boolean;
var numOrBool: number | boolean
var strOrNumOrBool: string | number | boolean;
var strOrC: string | C;
var numOrC: number | C;
var boolOrC: boolean | C;
var emptyObj: {};
var c: C;
// A type guard of the form typeof x === s,
// where s is a string literal with any value but 'string', 'number' or 'boolean',
// - when true, removes the primitive types string, number, and boolean from the type of x, or
// - when false, has no effect on the type of x.
if (typeof strOrNumOrBool === "Object") {
emptyObj = strOrNumOrBool; // {}
}
else {
var r1: string | number | boolean = strOrNumOrBool; // string | number | boolean
}
if (typeof strOrC === "Object") {
c = strOrC; // C
}
else {
var r2: string | C = strOrC; // string | C
}
if (typeof numOrC === "Object") {
c = numOrC; // C
}
else {
var r3: number | C = numOrC; // number | C
}
if (typeof boolOrC === "Object") {
c = boolOrC; // C
}
else {
var r4: boolean | C = boolOrC; // boolean | C
}
// A type guard of the form typeof x !== s, where s is a string literal,
// - when true, narrows the type of x by typeof x === s when false, or
// - when false, narrows the type of x by typeof x === s when true.
if (typeof strOrNumOrBool !== "Object") {
var r1: string | number | boolean = strOrNumOrBool; // string | number | boolean
}
else {
emptyObj = strOrNumOrBool; // {}
}
if (typeof strOrC !== "Object") {
var r2: string | C = strOrC; // string | C
}
else {
c = strOrC; // C
}
if (typeof numOrC !== "Object") {
var r3: number | C = numOrC; // number | C
}
else {
c = numOrC; // C
}
if (typeof boolOrC !== "Object") {
var r4: boolean | C = boolOrC; // boolean | C
}
else {
c = boolOrC; // C
}
//// [typeGuardOfFormTypeOfOther.js]
var C = (function () {
function C() {
}
return C;
})();
;
var str;
var bool;
var num;
var strOrNum;
var strOrBool;
var numOrBool;
var strOrNumOrBool;
var strOrC;
var numOrC;
var boolOrC;
var emptyObj;
var c;
// A type guard of the form typeof x === s,
// where s is a string literal with any value but 'string', 'number' or 'boolean',
// - when true, removes the primitive types string, number, and boolean from the type of x, or
// - when false, has no effect on the type of x.
if (typeof strOrNumOrBool === "Object") {
emptyObj = strOrNumOrBool; // {}
}
else {
var r1 = strOrNumOrBool; // string | number | boolean
}
if (typeof strOrC === "Object") {
c = strOrC; // C
}
else {
var r2 = strOrC; // string | C
}
if (typeof numOrC === "Object") {
c = numOrC; // C
}
else {
var r3 = numOrC; // number | C
}
if (typeof boolOrC === "Object") {
c = boolOrC; // C
}
else {
var r4 = boolOrC; // boolean | C
}
// A type guard of the form typeof x !== s, where s is a string literal,
// - when true, narrows the type of x by typeof x === s when false, or
// - when false, narrows the type of x by typeof x === s when true.
if (typeof strOrNumOrBool !== "Object") {
var r1 = strOrNumOrBool; // string | number | boolean
}
else {
emptyObj = strOrNumOrBool; // {}
}
if (typeof strOrC !== "Object") {
var r2 = strOrC; // string | C
}
else {
c = strOrC; // C
}
if (typeof numOrC !== "Object") {
var r3 = numOrC; // number | C
}
else {
c = numOrC; // C
}
if (typeof boolOrC !== "Object") {
var r4 = boolOrC; // boolean | C
}
else {
c = boolOrC; // C
}

View File

@@ -0,0 +1,180 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts ===
class C { private p: string };
>C : C
>p : string
var str: string;
>str : string
var bool: boolean;
>bool : boolean
var num: number;
>num : number
var strOrNum: string | number;
>strOrNum : string | number
var strOrBool: string | boolean;
>strOrBool : string | boolean
var numOrBool: number | boolean
>numOrBool : number | boolean
var strOrNumOrBool: string | number | boolean;
>strOrNumOrBool : string | number | boolean
var strOrC: string | C;
>strOrC : string | C
>C : C
var numOrC: number | C;
>numOrC : number | C
>C : C
var boolOrC: boolean | C;
>boolOrC : boolean | C
>C : C
var emptyObj: {};
>emptyObj : {}
var c: C;
>c : C
>C : C
// A type guard of the form typeof x === s,
// where s is a string literal with any value but 'string', 'number' or 'boolean',
// - when true, removes the primitive types string, number, and boolean from the type of x, or
// - when false, has no effect on the type of x.
if (typeof strOrNumOrBool === "Object") {
>typeof strOrNumOrBool === "Object" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : string | number | boolean
emptyObj = strOrNumOrBool; // {}
>emptyObj = strOrNumOrBool : {}
>emptyObj : {}
>strOrNumOrBool : {}
}
else {
var r1: string | number | boolean = strOrNumOrBool; // string | number | boolean
>r1 : string | number | boolean
>strOrNumOrBool : string | number | boolean
}
if (typeof strOrC === "Object") {
>typeof strOrC === "Object" : boolean
>typeof strOrC : string
>strOrC : string | C
c = strOrC; // C
>c = strOrC : C
>c : C
>strOrC : C
}
else {
var r2: string | C = strOrC; // string | C
>r2 : string | C
>C : C
>strOrC : string | C
}
if (typeof numOrC === "Object") {
>typeof numOrC === "Object" : boolean
>typeof numOrC : string
>numOrC : number | C
c = numOrC; // C
>c = numOrC : C
>c : C
>numOrC : C
}
else {
var r3: number | C = numOrC; // number | C
>r3 : number | C
>C : C
>numOrC : number | C
}
if (typeof boolOrC === "Object") {
>typeof boolOrC === "Object" : boolean
>typeof boolOrC : string
>boolOrC : boolean | C
c = boolOrC; // C
>c = boolOrC : C
>c : C
>boolOrC : C
}
else {
var r4: boolean | C = boolOrC; // boolean | C
>r4 : boolean | C
>C : C
>boolOrC : boolean | C
}
// A type guard of the form typeof x !== s, where s is a string literal,
// - when true, narrows the type of x by typeof x === s when false, or
// - when false, narrows the type of x by typeof x === s when true.
if (typeof strOrNumOrBool !== "Object") {
>typeof strOrNumOrBool !== "Object" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : string | number | boolean
var r1: string | number | boolean = strOrNumOrBool; // string | number | boolean
>r1 : string | number | boolean
>strOrNumOrBool : string | number | boolean
}
else {
emptyObj = strOrNumOrBool; // {}
>emptyObj = strOrNumOrBool : {}
>emptyObj : {}
>strOrNumOrBool : {}
}
if (typeof strOrC !== "Object") {
>typeof strOrC !== "Object" : boolean
>typeof strOrC : string
>strOrC : string | C
var r2: string | C = strOrC; // string | C
>r2 : string | C
>C : C
>strOrC : string | C
}
else {
c = strOrC; // C
>c = strOrC : C
>c : C
>strOrC : C
}
if (typeof numOrC !== "Object") {
>typeof numOrC !== "Object" : boolean
>typeof numOrC : string
>numOrC : number | C
var r3: number | C = numOrC; // number | C
>r3 : number | C
>C : C
>numOrC : number | C
}
else {
c = numOrC; // C
>c = numOrC : C
>c : C
>numOrC : C
}
if (typeof boolOrC !== "Object") {
>typeof boolOrC !== "Object" : boolean
>typeof boolOrC : string
>boolOrC : boolean | C
var r4: boolean | C = boolOrC; // boolean | C
>r4 : boolean | C
>C : C
>boolOrC : boolean | C
}
else {
c = boolOrC; // C
>c = boolOrC : C
>c : C
>boolOrC : C
}

View File

@@ -0,0 +1,169 @@
//// [typeGuardOfFormTypeOfString.ts]
class C { private p: string };
var str: string;
var bool: boolean;
var num: number;
var strOrNum: string | number;
var strOrBool: string | boolean;
var numOrBool: number | boolean
var strOrNumOrBool: string | number | boolean;
var strOrC: string | C;
var numOrC: number | C;
var boolOrC: boolean | C;
var c: C;
// A type guard of the form typeof x === s,
// where s is a string literal with the value 'string', 'number', or 'boolean',
// - when true, narrows the type of x to the given primitive type, or
// - when false, removes the primitive type from the type of x.
if (typeof strOrNum === "string") {
str = strOrNum; // string
}
else {
num === strOrNum; // number
}
if (typeof strOrBool === "string") {
str = strOrBool; // string
}
else {
bool = strOrBool; // boolean
}
if (typeof numOrBool === "string") {
str = numOrBool; // string
}
else {
var x : number | boolean = numOrBool; // number | boolean
}
if (typeof strOrNumOrBool === "string") {
str = strOrNumOrBool; // string
}
else {
numOrBool = strOrNumOrBool; // number | boolean
}
if (typeof strOrC === "string") {
str = strOrC; // string
}
else {
c = strOrC; // C
}
// A type guard of the form typeof x !== s, where s is a string literal,
// - when true, narrows the type of x by typeof x === s when false, or
// - when false, narrows the type of x by typeof x === s when true.
if (typeof strOrNum !== "string") {
num === strOrNum; // number
}
else {
str = strOrNum; // string
}
if (typeof strOrBool !== "string") {
bool = strOrBool; // boolean
}
else {
str = strOrBool; // string
}
if (typeof numOrBool !== "string") {
var x: number | boolean = numOrBool; // number | boolean
}
else {
str = numOrBool; // string
}
if (typeof strOrNumOrBool !== "string") {
numOrBool = strOrNumOrBool; // number | boolean
}
else {
str = strOrNumOrBool; // string
}
if (typeof strOrC !== "string") {
c = strOrC; // C
}
else {
str = strOrC; // string
}
//// [typeGuardOfFormTypeOfString.js]
var C = (function () {
function C() {
}
return C;
})();
;
var str;
var bool;
var num;
var strOrNum;
var strOrBool;
var numOrBool;
var strOrNumOrBool;
var strOrC;
var numOrC;
var boolOrC;
var c;
// A type guard of the form typeof x === s,
// where s is a string literal with the value 'string', 'number', or 'boolean',
// - when true, narrows the type of x to the given primitive type, or
// - when false, removes the primitive type from the type of x.
if (typeof strOrNum === "string") {
str = strOrNum; // string
}
else {
num === strOrNum; // number
}
if (typeof strOrBool === "string") {
str = strOrBool; // string
}
else {
bool = strOrBool; // boolean
}
if (typeof numOrBool === "string") {
str = numOrBool; // string
}
else {
var x = numOrBool; // number | boolean
}
if (typeof strOrNumOrBool === "string") {
str = strOrNumOrBool; // string
}
else {
numOrBool = strOrNumOrBool; // number | boolean
}
if (typeof strOrC === "string") {
str = strOrC; // string
}
else {
c = strOrC; // C
}
// A type guard of the form typeof x !== s, where s is a string literal,
// - when true, narrows the type of x by typeof x === s when false, or
// - when false, narrows the type of x by typeof x === s when true.
if (typeof strOrNum !== "string") {
num === strOrNum; // number
}
else {
str = strOrNum; // string
}
if (typeof strOrBool !== "string") {
bool = strOrBool; // boolean
}
else {
str = strOrBool; // string
}
if (typeof numOrBool !== "string") {
var x = numOrBool; // number | boolean
}
else {
str = numOrBool; // string
}
if (typeof strOrNumOrBool !== "string") {
numOrBool = strOrNumOrBool; // number | boolean
}
else {
str = strOrNumOrBool; // string
}
if (typeof strOrC !== "string") {
c = strOrC; // C
}
else {
str = strOrC; // string
}

View File

@@ -0,0 +1,208 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfString.ts ===
class C { private p: string };
>C : C
>p : string
var str: string;
>str : string
var bool: boolean;
>bool : boolean
var num: number;
>num : number
var strOrNum: string | number;
>strOrNum : string | number
var strOrBool: string | boolean;
>strOrBool : string | boolean
var numOrBool: number | boolean
>numOrBool : number | boolean
var strOrNumOrBool: string | number | boolean;
>strOrNumOrBool : string | number | boolean
var strOrC: string | C;
>strOrC : string | C
>C : C
var numOrC: number | C;
>numOrC : number | C
>C : C
var boolOrC: boolean | C;
>boolOrC : boolean | C
>C : C
var c: C;
>c : C
>C : C
// A type guard of the form typeof x === s,
// where s is a string literal with the value 'string', 'number', or 'boolean',
// - when true, narrows the type of x to the given primitive type, or
// - when false, removes the primitive type from the type of x.
if (typeof strOrNum === "string") {
>typeof strOrNum === "string" : boolean
>typeof strOrNum : string
>strOrNum : string | number
str = strOrNum; // string
>str = strOrNum : string
>str : string
>strOrNum : string
}
else {
num === strOrNum; // number
>num === strOrNum : boolean
>num : number
>strOrNum : number
}
if (typeof strOrBool === "string") {
>typeof strOrBool === "string" : boolean
>typeof strOrBool : string
>strOrBool : string | boolean
str = strOrBool; // string
>str = strOrBool : string
>str : string
>strOrBool : string
}
else {
bool = strOrBool; // boolean
>bool = strOrBool : boolean
>bool : boolean
>strOrBool : boolean
}
if (typeof numOrBool === "string") {
>typeof numOrBool === "string" : boolean
>typeof numOrBool : string
>numOrBool : number | boolean
str = numOrBool; // string
>str = numOrBool : string
>str : string
>numOrBool : string
}
else {
var x : number | boolean = numOrBool; // number | boolean
>x : number | boolean
>numOrBool : number | boolean
}
if (typeof strOrNumOrBool === "string") {
>typeof strOrNumOrBool === "string" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : string | number | boolean
str = strOrNumOrBool; // string
>str = strOrNumOrBool : string
>str : string
>strOrNumOrBool : string
}
else {
numOrBool = strOrNumOrBool; // number | boolean
>numOrBool = strOrNumOrBool : number | boolean
>numOrBool : number | boolean
>strOrNumOrBool : number | boolean
}
if (typeof strOrC === "string") {
>typeof strOrC === "string" : boolean
>typeof strOrC : string
>strOrC : string | C
str = strOrC; // string
>str = strOrC : string
>str : string
>strOrC : string
}
else {
c = strOrC; // C
>c = strOrC : C
>c : C
>strOrC : C
}
// A type guard of the form typeof x !== s, where s is a string literal,
// - when true, narrows the type of x by typeof x === s when false, or
// - when false, narrows the type of x by typeof x === s when true.
if (typeof strOrNum !== "string") {
>typeof strOrNum !== "string" : boolean
>typeof strOrNum : string
>strOrNum : string | number
num === strOrNum; // number
>num === strOrNum : boolean
>num : number
>strOrNum : number
}
else {
str = strOrNum; // string
>str = strOrNum : string
>str : string
>strOrNum : string
}
if (typeof strOrBool !== "string") {
>typeof strOrBool !== "string" : boolean
>typeof strOrBool : string
>strOrBool : string | boolean
bool = strOrBool; // boolean
>bool = strOrBool : boolean
>bool : boolean
>strOrBool : boolean
}
else {
str = strOrBool; // string
>str = strOrBool : string
>str : string
>strOrBool : string
}
if (typeof numOrBool !== "string") {
>typeof numOrBool !== "string" : boolean
>typeof numOrBool : string
>numOrBool : number | boolean
var x: number | boolean = numOrBool; // number | boolean
>x : number | boolean
>numOrBool : number | boolean
}
else {
str = numOrBool; // string
>str = numOrBool : string
>str : string
>numOrBool : string
}
if (typeof strOrNumOrBool !== "string") {
>typeof strOrNumOrBool !== "string" : boolean
>typeof strOrNumOrBool : string
>strOrNumOrBool : string | number | boolean
numOrBool = strOrNumOrBool; // number | boolean
>numOrBool = strOrNumOrBool : number | boolean
>numOrBool : number | boolean
>strOrNumOrBool : number | boolean
}
else {
str = strOrNumOrBool; // string
>str = strOrNumOrBool : string
>str : string
>strOrNumOrBool : string
}
if (typeof strOrC !== "string") {
>typeof strOrC !== "string" : boolean
>typeof strOrC : string
>strOrC : string | C
c = strOrC; // C
>c = strOrC : C
>c : C
>strOrC : C
}
else {
str = strOrC; // string
>str = strOrC : string
>str : string
>strOrC : string
}

View File

@@ -0,0 +1,75 @@
//// [typeGuardsDefeat.ts]
// Also note that it is possible to defeat a type guard by calling a function that changes the
// type of the guarded variable.
function foo(x: number | string) {
function f() {
x = 10;
}
if (typeof x === "string") {
f();
return x.length; // string
}
else {
return x++; // number
}
}
function foo2(x: number | string) {
if (typeof x === "string") {
return x.length; // string
}
else {
(function f() {
x = 10;
})();
return x++; // number
}
}
function foo3(x: number | string) {
if (typeof x === "string") {
return x.length; // string
}
else {
(() => {
x = 10;
})();
return x++; // number
}
}
//// [typeGuardsDefeat.js]
// Also note that it is possible to defeat a type guard by calling a function that changes the
// type of the guarded variable.
function foo(x) {
function f() {
x = 10;
}
if (typeof x === "string") {
f();
return x.length; // string
}
else {
return x++; // number
}
}
function foo2(x) {
if (typeof x === "string") {
return x.length; // string
}
else {
(function f() {
x = 10;
})();
return x++; // number
}
}
function foo3(x) {
if (typeof x === "string") {
return x.length; // string
}
else {
(function () {
x = 10;
})();
return x++; // number
}
}

View File

@@ -0,0 +1,95 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsDefeat.ts ===
// Also note that it is possible to defeat a type guard by calling a function that changes the
// type of the guarded variable.
function foo(x: number | string) {
>foo : (x: string | number) => number
>x : string | number
function f() {
>f : () => void
x = 10;
>x = 10 : number
>x : string | number
}
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
f();
>f() : void
>f : () => void
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: string | number) => number
>x : string | number
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
return x.length; // string
>x.length : number
>x : string
>length : number
}
else {
(function f() {
>(function f() { x = 10; })() : void
>(function f() { x = 10; }) : () => void
>function f() { x = 10; } : () => void
>f : () => void
x = 10;
>x = 10 : number
>x : string | number
})();
return x++; // number
>x++ : number
>x : number
}
}
function foo3(x: number | string) {
>foo3 : (x: string | number) => number
>x : string | number
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
return x.length; // string
>x.length : number
>x : string
>length : number
}
else {
(() => {
>(() => { x = 10; })() : void
>(() => { x = 10; }) : () => void
>() => { x = 10; } : () => void
x = 10;
>x = 10 : number
>x : string | number
})();
return x++; // number
>x++ : number
>x : number
}
}

View File

@@ -0,0 +1,209 @@
//// [typeGuardsInClassAccessors.ts]
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num: number;
var strOrNum: string | number;
var var1: string | number;
class ClassWithAccessors {
// Inside public accessor getter
get p1() {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
return strOrNum;
}
// Inside public accessor setter
set p1(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// parameter of function declaration
num = typeof param === "string" && param.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
}
// Inside private accessor getter
private get pp1() {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
return strOrNum;
}
// Inside private accessor setter
private set pp1(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// parameter of function declaration
num = typeof param === "string" && param.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
}
// Inside static accessor getter
static get s1() {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
return strOrNum;
}
// Inside static accessor setter
static set s1(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// parameter of function declaration
num = typeof param === "string" && param.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
}
// Inside private static accessor getter
private static get ss1() {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
return strOrNum;
}
// Inside private static accessor setter
private static set ss1(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// parameter of function declaration
num = typeof param === "string" && param.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
}
}
//// [typeGuardsInClassAccessors.js]
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num;
var strOrNum;
var var1;
var ClassWithAccessors = (function () {
function ClassWithAccessors() {
}
Object.defineProperty(ClassWithAccessors.prototype, "p1", {
// Inside public accessor getter
get: function () {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2;
num = typeof var2 === "string" && var2.length; // string
return strOrNum;
},
// Inside public accessor setter
set: function (param) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// parameter of function declaration
num = typeof param === "string" && param.length; // string
// variables in function declaration
var var2;
num = typeof var2 === "string" && var2.length; // string
},
enumerable: true,
configurable: true
});
Object.defineProperty(ClassWithAccessors.prototype, "pp1", {
// Inside private accessor getter
get: function () {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2;
num = typeof var2 === "string" && var2.length; // string
return strOrNum;
},
// Inside private accessor setter
set: function (param) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// parameter of function declaration
num = typeof param === "string" && param.length; // string
// variables in function declaration
var var2;
num = typeof var2 === "string" && var2.length; // string
},
enumerable: true,
configurable: true
});
Object.defineProperty(ClassWithAccessors, "s1", {
// Inside static accessor getter
get: function () {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2;
num = typeof var2 === "string" && var2.length; // string
return strOrNum;
},
// Inside static accessor setter
set: function (param) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// parameter of function declaration
num = typeof param === "string" && param.length; // string
// variables in function declaration
var var2;
num = typeof var2 === "string" && var2.length; // string
},
enumerable: true,
configurable: true
});
Object.defineProperty(ClassWithAccessors, "ss1", {
// Inside private static accessor getter
get: function () {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2;
num = typeof var2 === "string" && var2.length; // string
return strOrNum;
},
// Inside private static accessor setter
set: function (param) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// parameter of function declaration
num = typeof param === "string" && param.length; // string
// variables in function declaration
var var2;
num = typeof var2 === "string" && var2.length; // string
},
enumerable: true,
configurable: true
});
return ClassWithAccessors;
})();

View File

@@ -0,0 +1,332 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInClassAccessors.ts ===
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num: number;
>num : number
var strOrNum: string | number;
>strOrNum : string | number
var var1: string | number;
>var1 : string | number
class ClassWithAccessors {
>ClassWithAccessors : ClassWithAccessors
// Inside public accessor getter
get p1() {
>p1 : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// variables in function declaration
var var2: string | number;
>var2 : string | number
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
return strOrNum;
>strOrNum : string | number
}
// Inside public accessor setter
set p1(param: string | number) {
>p1 : string | number
>param : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// parameter of function declaration
num = typeof param === "string" && param.length; // string
>num = typeof param === "string" && param.length : number
>num : number
>typeof param === "string" && param.length : number
>typeof param === "string" : boolean
>typeof param : string
>param : string | number
>param.length : number
>param : string
>length : number
// variables in function declaration
var var2: string | number;
>var2 : string | number
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
}
// Inside private accessor getter
private get pp1() {
>pp1 : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// variables in function declaration
var var2: string | number;
>var2 : string | number
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
return strOrNum;
>strOrNum : string | number
}
// Inside private accessor setter
private set pp1(param: string | number) {
>pp1 : string | number
>param : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// parameter of function declaration
num = typeof param === "string" && param.length; // string
>num = typeof param === "string" && param.length : number
>num : number
>typeof param === "string" && param.length : number
>typeof param === "string" : boolean
>typeof param : string
>param : string | number
>param.length : number
>param : string
>length : number
// variables in function declaration
var var2: string | number;
>var2 : string | number
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
}
// Inside static accessor getter
static get s1() {
>s1 : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// variables in function declaration
var var2: string | number;
>var2 : string | number
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
return strOrNum;
>strOrNum : string | number
}
// Inside static accessor setter
static set s1(param: string | number) {
>s1 : string | number
>param : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// parameter of function declaration
num = typeof param === "string" && param.length; // string
>num = typeof param === "string" && param.length : number
>num : number
>typeof param === "string" && param.length : number
>typeof param === "string" : boolean
>typeof param : string
>param : string | number
>param.length : number
>param : string
>length : number
// variables in function declaration
var var2: string | number;
>var2 : string | number
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
}
// Inside private static accessor getter
private static get ss1() {
>ss1 : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// variables in function declaration
var var2: string | number;
>var2 : string | number
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
return strOrNum;
>strOrNum : string | number
}
// Inside private static accessor setter
private static set ss1(param: string | number) {
>ss1 : string | number
>param : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// parameter of function declaration
num = typeof param === "string" && param.length; // string
>num = typeof param === "string" && param.length : number
>num : number
>typeof param === "string" && param.length : number
>typeof param === "string" : boolean
>typeof param : string
>param : string | number
>param.length : number
>param : string
>length : number
// variables in function declaration
var var2: string | number;
>var2 : string | number
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
}
}

View File

@@ -0,0 +1,128 @@
//// [typeGuardsInClassMethods.ts]
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num: number;
var var1: string | number;
class C1 {
constructor(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
}
// Inside function declaration
private p1(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
}
// Inside function declaration
p2(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
}
// Inside function declaration
private static s1(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
}
// Inside function declaration
static s2(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
}
}
//// [typeGuardsInClassMethods.js]
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num;
var var1;
var C1 = (function () {
function C1(param) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
}
// Inside function declaration
C1.prototype.p1 = function (param) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
};
// Inside function declaration
C1.prototype.p2 = function (param) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
};
// Inside function declaration
C1.s1 = function (param) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
};
// Inside function declaration
C1.s2 = function (param) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
};
return C1;
})();

View File

@@ -0,0 +1,234 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInClassMethods.ts ===
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num: number;
>num : number
var var1: string | number;
>var1 : string | number
class C1 {
>C1 : C1
constructor(param: string | number) {
>param : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// variables in function declaration
var var2: string | number;
>var2 : string | number
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
// parameters in function declaration
num = typeof param === "string" && param.length; // string
>num = typeof param === "string" && param.length : number
>num : number
>typeof param === "string" && param.length : number
>typeof param === "string" : boolean
>typeof param : string
>param : string | number
>param.length : number
>param : string
>length : number
}
// Inside function declaration
private p1(param: string | number) {
>p1 : (param: string | number) => void
>param : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// variables in function declaration
var var2: string | number;
>var2 : string | number
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
// parameters in function declaration
num = typeof param === "string" && param.length; // string
>num = typeof param === "string" && param.length : number
>num : number
>typeof param === "string" && param.length : number
>typeof param === "string" : boolean
>typeof param : string
>param : string | number
>param.length : number
>param : string
>length : number
}
// Inside function declaration
p2(param: string | number) {
>p2 : (param: string | number) => void
>param : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// variables in function declaration
var var2: string | number;
>var2 : string | number
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
// parameters in function declaration
num = typeof param === "string" && param.length; // string
>num = typeof param === "string" && param.length : number
>num : number
>typeof param === "string" && param.length : number
>typeof param === "string" : boolean
>typeof param : string
>param : string | number
>param.length : number
>param : string
>length : number
}
// Inside function declaration
private static s1(param: string | number) {
>s1 : (param: string | number) => void
>param : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// variables in function declaration
var var2: string | number;
>var2 : string | number
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
// parameters in function declaration
num = typeof param === "string" && param.length; // string
>num = typeof param === "string" && param.length : number
>num : number
>typeof param === "string" && param.length : number
>typeof param === "string" : boolean
>typeof param : string
>param : string | number
>param.length : number
>param : string
>length : number
}
// Inside function declaration
static s2(param: string | number) {
>s2 : (param: string | number) => void
>param : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// variables in function declaration
var var2: string | number;
>var2 : string | number
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
// parameters in function declaration
num = typeof param === "string" && param.length; // string
>num = typeof param === "string" && param.length : number
>num : number
>typeof param === "string" && param.length : number
>typeof param === "string" : boolean
>typeof param : string
>param : string | number
>param.length : number
>param : string
>length : number
}
}

View File

@@ -0,0 +1,160 @@
//// [typeGuardsInConditionalExpression.ts]
// In the true expression of a conditional expression,
// the type of a variable or parameter is narrowed by any type guard in the condition when true,
// provided the true expression contains no assignments to the variable or parameter.
// In the false expression of a conditional expression,
// the type of a variable or parameter is narrowed by any type guard in the condition when false,
// provided the false expression contains no assignments to the variable or parameter.
function foo(x: number | string) {
return typeof x === "string"
? x.length // 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
}
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
}
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
}
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
}
function foo6(x: number | string) {
// Modify in both branches
return typeof x === "string"
? (x = 10 && x) // string | number
: (x = "hello" && x); // string | number
}
function foo7(x: number | string | boolean) {
return typeof x === "string"
? x === "hello" // string
: typeof x === "boolean"
? x // boolean
: x == 10; // number
}
function foo8(x: number | string | boolean) {
var b: number | boolean;
return typeof x === "string"
? x === "hello"
: ((b = x) && // number | boolean
(typeof x === "boolean"
? x // boolean
: x == 10)); // number
}
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
}
function foo10(x: number | string | boolean) {
// Mixing typeguards
var b: boolean | number;
return typeof x === "string"
? x // string
: ((b = x) // x is number | boolean
&& typeof x === "number"
&& x.toString()); // x is number
}
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
&& typeof x === "number"
&& (x = 10) // assignment to x
&& x); // x is number | boolean | string
}
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
&& typeof x === "number"
&& x); // x is number
}
//// [typeGuardsInConditionalExpression.js]
// In the true expression of a conditional expression,
// the type of a variable or parameter is narrowed by any type guard in the condition when true,
// provided the true expression contains no assignments to the variable or parameter.
// In the false expression of a conditional expression,
// the type of a variable or parameter is narrowed by any type guard in the condition when false,
// provided the false expression contains no assignments to the variable or parameter.
function foo(x) {
return typeof x === "string" ? x.length : 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) : x; // string | 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) : x; // string | 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 : (x = 10 && x); // string | number
}
function foo5(x) {
// false branch updates the variable - so here it is not number
return typeof x === "string" ? x : (x = "hello" && x); // string | number
}
function foo6(x) {
// Modify in both branches
return typeof x === "string" ? (x = 10 && x) : (x = "hello" && x); // string | number
}
function foo7(x) {
return typeof x === "string" ? x === "hello" : typeof x === "boolean" ? x : x == 10; // number
}
function foo8(x) {
var b;
return typeof x === "string" ? x === "hello" : ((b = x) && (typeof x === "boolean" ? x : x == 10)); // number
}
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") : x === 10; // number
}
function foo10(x) {
// Mixing typeguards
var b;
return typeof x === "string" ? x : ((b = x) && typeof x === "number" && x.toString()); // x is number
}
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 : ((b = x) && typeof x === "number" && (x = 10) && x); // x is number | boolean | string
}
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) : ((b = x) && typeof x === "number" && x); // x is number
}

View File

@@ -0,0 +1,356 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInConditionalExpression.ts ===
// In the true expression of a conditional expression,
// the type of a variable or parameter is narrowed by any type guard in the condition when true,
// provided the true expression contains no assignments to the variable or parameter.
// In the false expression of a conditional expression,
// the type of a variable or parameter is narrowed by any type guard in the condition when false,
// provided the false expression contains no assignments to the variable or parameter.
function foo(x: number | string) {
>foo : (x: string | number) => number
>x : string | number
return typeof x === "string"
>typeof x === "string" ? x.length // string : x++ : number
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
? x.length // string
>x.length : number
>x : string
>length : number
: x++; // number
>x++ : number
>x : number
}
function foo2(x: number | string) {
>foo2 : (x: string | number) => string | number
>x : string | number
// 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 : string | number
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
? (x = 10 && x)// string | number
>(x = 10 && x) : string | number
>x = 10 && x : string | number
>x : string | number
>10 && x : string | number
>x : string | number
: x; // string | number
>x : string | number
}
function foo3(x: number | string) {
>foo3 : (x: string | number) => string | number
>x : string | number
// 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 : string | number
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
? (x = "Hello" && x) // string | number
>(x = "Hello" && x) : string | number
>x = "Hello" && x : string | number
>x : string | number
>"Hello" && x : string | number
>x : string | number
: x; // string | number
>x : string | number
}
function foo4(x: number | string) {
>foo4 : (x: string | number) => string | number
>x : string | number
// 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) : string | number
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
? x // string | number
>x : string | number
: (x = 10 && x); // string | number
>(x = 10 && x) : string | number
>x = 10 && x : string | number
>x : string | number
>10 && x : string | number
>x : string | number
}
function foo5(x: number | string) {
>foo5 : (x: string | number) => string | number
>x : string | number
// false branch updates the variable - so here it is not number
return typeof x === "string"
>typeof x === "string" ? x // string | number : (x = "hello" && x) : string | number
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
? x // string | number
>x : string | number
: (x = "hello" && x); // string | number
>(x = "hello" && x) : string | number
>x = "hello" && x : string | number
>x : string | number
>"hello" && x : string | number
>x : string | number
}
function foo6(x: number | string) {
>foo6 : (x: string | number) => string | number
>x : string | number
// Modify in both branches
return typeof x === "string"
>typeof x === "string" ? (x = 10 && x) // string | number : (x = "hello" && x) : string | number
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
? (x = 10 && x) // string | number
>(x = 10 && x) : string | number
>x = 10 && x : string | number
>x : string | number
>10 && x : string | number
>x : string | number
: (x = "hello" && x); // string | number
>(x = "hello" && x) : string | number
>x = "hello" && x : string | number
>x : string | number
>"hello" && x : string | number
>x : string | number
}
function foo7(x: number | string | boolean) {
>foo7 : (x: string | number | boolean) => boolean
>x : string | number | boolean
return typeof x === "string"
>typeof x === "string" ? x === "hello" // string : typeof x === "boolean" ? x // boolean : x == 10 : boolean
>typeof x === "string" : boolean
>typeof x : string
>x : string | number | boolean
? x === "hello" // string
>x === "hello" : boolean
>x : string
: typeof x === "boolean"
>typeof x === "boolean" ? x // boolean : x == 10 : boolean
>typeof x === "boolean" : boolean
>typeof x : string
>x : number | boolean
? x // boolean
>x : boolean
: x == 10; // number
>x == 10 : boolean
>x : number
}
function foo8(x: number | string | boolean) {
>foo8 : (x: string | number | boolean) => boolean
>x : string | number | boolean
var b: number | boolean;
>b : number | boolean
return typeof x === "string"
>typeof x === "string" ? x === "hello" : ((b = x) && // number | boolean (typeof x === "boolean" ? x // boolean : x == 10)) : boolean
>typeof x === "string" : boolean
>typeof x : string
>x : string | number | boolean
? x === "hello"
>x === "hello" : boolean
>x : string
: ((b = x) && // number | boolean
>((b = x) && // number | boolean (typeof x === "boolean" ? x // boolean : x == 10)) : boolean
>(b = x) && // number | boolean (typeof x === "boolean" ? x // boolean : x == 10) : boolean
>(b = x) : number | boolean
>b = x : number | boolean
>b : number | boolean
>x : number | boolean
(typeof x === "boolean"
>(typeof x === "boolean" ? x // boolean : x == 10) : boolean
>typeof x === "boolean" ? x // boolean : x == 10 : boolean
>typeof x === "boolean" : boolean
>typeof x : string
>x : number | boolean
? x // boolean
>x : boolean
: x == 10)); // number
>x == 10 : boolean
>x : number
}
function foo9(x: number | string) {
>foo9 : (x: string | number) => boolean
>x : string | number
var y = 10;
>y : number
// 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" : boolean
>typeof x : string
>x : string | number
? ((y = x.length) && x === "hello") // string
>((y = x.length) && x === "hello") : boolean
>(y = x.length) && x === "hello" : boolean
>(y = x.length) : number
>y = x.length : number
>y : number
>x.length : number
>x : string
>length : number
>x === "hello" : boolean
>x : string
: x === 10; // number
>x === 10 : boolean
>x : number
}
function foo10(x: number | string | boolean) {
>foo10 : (x: string | number | boolean) => string
>x : string | number | boolean
// Mixing typeguards
var b: boolean | number;
>b : number | boolean
return typeof x === "string"
>typeof x === "string" ? x // string : ((b = x) // x is number | boolean && typeof x === "number" && x.toString()) : string
>typeof x === "string" : boolean
>typeof x : string
>x : string | number | boolean
? x // string
>x : string
: ((b = x) // x is number | boolean
>((b = x) // x is number | boolean && typeof x === "number" && x.toString()) : string
>(b = x) // x is number | boolean && typeof x === "number" && x.toString() : string
>(b = x) // x is number | boolean && typeof x === "number" : boolean
>(b = x) : number | boolean
>b = x : number | boolean
>b : number | boolean
>x : number | boolean
&& typeof x === "number"
>typeof x === "number" : boolean
>typeof x : string
>x : number | boolean
&& x.toString()); // x is number
>x.toString() : string
>x.toString : (radix?: number) => string
>x : number
>toString : (radix?: number) => string
}
function foo11(x: number | string | boolean) {
>foo11 : (x: string | number | boolean) => string | number | boolean
>x : string | number | boolean
// Mixing typeguards
// Assigning value to x deep inside another guard stops narrowing of type too
var b: number | boolean | string;
>b : string | number | boolean
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) : string | number | boolean
>typeof x === "string" : boolean
>typeof x : string
>x : string | number | boolean
? x // number | boolean | string - changed in the false branch
>x : string | number | boolean
: ((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) : string | number | boolean
>(b = x) // x is number | boolean | string - because the assignment changed it && typeof x === "number" && (x = 10) // assignment to x && x : string | number | 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) : string | number | boolean
>b = x : string | number | boolean
>b : string | number | boolean
>x : string | number | boolean
&& typeof x === "number"
>typeof x === "number" : boolean
>typeof x : string
>x : string | number | boolean
&& (x = 10) // assignment to x
>(x = 10) : number
>x = 10 : number
>x : string | number | boolean
&& x); // x is number | boolean | string
>x : string | number | boolean
}
function foo12(x: number | string | boolean) {
>foo12 : (x: string | number | boolean) => number
>x : string | number | boolean
// Mixing typeguards
// Assigning value to x in outer guard shouldn't stop narrowing in the inner expression
var b: number | boolean | string;
>b : string | number | boolean
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" : boolean
>typeof x : string
>x : string | number | boolean
? (x = 10 && x.toString().length) // number | boolean | string - changed here
>(x = 10 && x.toString().length) : number
>x = 10 && x.toString().length : number
>x : string | number | boolean
>10 && x.toString().length : number
>x.toString().length : number
>x.toString() : string
>x.toString : () => string
>x : string | number | boolean
>toString : () => 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) : string | number | boolean
>b = x : string | number | boolean
>b : string | number | boolean
>x : string | number | boolean
&& typeof x === "number"
>typeof x === "number" : boolean
>typeof x : string
>x : string | number | boolean
&& x); // x is number
>x : number
}

View File

@@ -0,0 +1,47 @@
//// [typeGuardsInExternalModule.ts]
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// local variable in external module
var num: number;
var var1: string | number;
if (typeof var1 === "string") {
num = var1.length; // string
}
else {
num = var1; // number
}
// exported variable in external module
var strOrNum: string | number;
export var var2: string | number;
if (typeof var2 === "string") {
// export makes the var property and not variable
strOrNum = var2; // string | number
}
else {
strOrNum = var2; // number | string
}
//// [typeGuardsInExternalModule.js]
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// local variable in external module
var num;
var var1;
if (typeof var1 === "string") {
num = var1.length; // string
}
else {
num = var1; // number
}
// exported variable in external module
var strOrNum;
exports.var2;
if (typeof exports.var2 === "string") {
// export makes the var property and not variable
strOrNum = exports.var2; // string | number
}
else {
strOrNum = exports.var2; // number | string
}

View File

@@ -0,0 +1,54 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInExternalModule.ts ===
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// local variable in external module
var num: number;
>num : number
var var1: string | number;
>var1 : string | number
if (typeof var1 === "string") {
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
num = var1.length; // string
>num = var1.length : number
>num : number
>var1.length : number
>var1 : string
>length : number
}
else {
num = var1; // number
>num = var1 : number
>num : number
>var1 : number
}
// exported variable in external module
var strOrNum: string | number;
>strOrNum : string | number
export var var2: string | number;
>var2 : string | number
if (typeof var2 === "string") {
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
// export makes the var property and not variable
strOrNum = var2; // string | number
>strOrNum = var2 : string | number
>strOrNum : string | number
>var2 : string | number
}
else {
strOrNum = var2; // number | string
>strOrNum = var2 : string | number
>strOrNum : string | number
>var2 : string | number
}

View File

@@ -0,0 +1,165 @@
//// [typeGuardsInFunction.ts]
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num: number;
var var1: string | number;
// Inside function declaration
function f(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
}
// local function declaration
function f1(param: string | number) {
var var2: string | number;
function f2(param1: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables from outer function declaration
num = typeof var2 === "string" && var2.length; // string
// parameters in outer declaration
num = typeof param === "string" && param.length; // string
// local
var var3: string | number;
num = typeof var3 === "string" && var3.length; // string
num = typeof param1 === "string" && param1.length; // string
}
}
// Function expression
function f2(param: string | number) {
// variables in function declaration
var var2: string | number;
// variables in function expressions
var r = function (param1: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables from outer function declaration
num = typeof var2 === "string" && var2.length; // string
// parameters in outer declaration
num = typeof param === "string" && param.length; // string
// local
var var3: string | number;
num = typeof var3 === "string" && var3.length; // string
num = typeof param1 === "string" && param1.length; // string
} (param);
}
// Arrow expression
function f3(param: string | number) {
// variables in function declaration
var var2: string | number;
// variables in function expressions
var r = ((param1: string | number) => {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables from outer function declaration
num = typeof var2 === "string" && var2.length; // string
// parameters in outer declaration
num = typeof param === "string" && param.length; // string
// local
var var3: string | number;
num = typeof var3 === "string" && var3.length; // string
num = typeof param1 === "string" && param1.length; // string
})(param);
}
// Return type of function
// Inside function declaration
var strOrNum: string | number;
function f4() {
var var2: string | number = strOrNum;
return var2;
}
strOrNum = typeof f4() === "string" && f4(); // string | number
//// [typeGuardsInFunction.js]
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num;
var var1;
// Inside function declaration
function f(param) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
}
// local function declaration
function f1(param) {
var var2;
function f2(param1) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables from outer function declaration
num = typeof var2 === "string" && var2.length; // string
// parameters in outer declaration
num = typeof param === "string" && param.length; // string
// local
var var3;
num = typeof var3 === "string" && var3.length; // string
num = typeof param1 === "string" && param1.length; // string
}
}
// Function expression
function f2(param) {
// variables in function declaration
var var2;
// variables in function expressions
var r = function (param1) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables from outer function declaration
num = typeof var2 === "string" && var2.length; // string
// parameters in outer declaration
num = typeof param === "string" && param.length; // string
// local
var var3;
num = typeof var3 === "string" && var3.length; // string
num = typeof param1 === "string" && param1.length; // string
}(param);
}
// Arrow expression
function f3(param) {
// variables in function declaration
var var2;
// variables in function expressions
var r = (function (param1) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables from outer function declaration
num = typeof var2 === "string" && var2.length; // string
// parameters in outer declaration
num = typeof param === "string" && param.length; // string
// local
var var3;
num = typeof var3 === "string" && var3.length; // string
num = typeof param1 === "string" && param1.length; // string
})(param);
}
// Return type of function
// Inside function declaration
var strOrNum;
function f4() {
var var2 = strOrNum;
return var2;
}
strOrNum = typeof f4() === "string" && f4(); // string | number

View File

@@ -0,0 +1,319 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInFunction.ts ===
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num: number;
>num : number
var var1: string | number;
>var1 : string | number
// Inside function declaration
function f(param: string | number) {
>f : (param: string | number) => void
>param : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// variables in function declaration
var var2: string | number;
>var2 : string | number
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
// parameters in function declaration
num = typeof param === "string" && param.length; // string
>num = typeof param === "string" && param.length : number
>num : number
>typeof param === "string" && param.length : number
>typeof param === "string" : boolean
>typeof param : string
>param : string | number
>param.length : number
>param : string
>length : number
}
// local function declaration
function f1(param: string | number) {
>f1 : (param: string | number) => void
>param : string | number
var var2: string | number;
>var2 : string | number
function f2(param1: string | number) {
>f2 : (param1: string | number) => void
>param1 : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// variables from outer function declaration
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
// parameters in outer declaration
num = typeof param === "string" && param.length; // string
>num = typeof param === "string" && param.length : number
>num : number
>typeof param === "string" && param.length : number
>typeof param === "string" : boolean
>typeof param : string
>param : string | number
>param.length : number
>param : string
>length : number
// local
var var3: string | number;
>var3 : string | number
num = typeof var3 === "string" && var3.length; // string
>num = typeof var3 === "string" && var3.length : number
>num : number
>typeof var3 === "string" && var3.length : number
>typeof var3 === "string" : boolean
>typeof var3 : string
>var3 : string | number
>var3.length : number
>var3 : string
>length : number
num = typeof param1 === "string" && param1.length; // string
>num = typeof param1 === "string" && param1.length : number
>num : number
>typeof param1 === "string" && param1.length : number
>typeof param1 === "string" : boolean
>typeof param1 : string
>param1 : string | number
>param1.length : number
>param1 : string
>length : number
}
}
// Function expression
function f2(param: string | number) {
>f2 : (param: string | number) => void
>param : string | number
// variables in function declaration
var var2: string | number;
>var2 : string | number
// variables in function expressions
var r = function (param1: string | number) {
>r : void
>function (param1: string | number) { // global vars in function declaration num = typeof var1 === "string" && var1.length; // string // variables from outer function declaration num = typeof var2 === "string" && var2.length; // string // parameters in outer declaration num = typeof param === "string" && param.length; // string // local var var3: string | number; num = typeof var3 === "string" && var3.length; // string num = typeof param1 === "string" && param1.length; // string } (param) : void
>function (param1: string | number) { // global vars in function declaration num = typeof var1 === "string" && var1.length; // string // variables from outer function declaration num = typeof var2 === "string" && var2.length; // string // parameters in outer declaration num = typeof param === "string" && param.length; // string // local var var3: string | number; num = typeof var3 === "string" && var3.length; // string num = typeof param1 === "string" && param1.length; // string } : (param1: string | number) => void
>param1 : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// variables from outer function declaration
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
// parameters in outer declaration
num = typeof param === "string" && param.length; // string
>num = typeof param === "string" && param.length : number
>num : number
>typeof param === "string" && param.length : number
>typeof param === "string" : boolean
>typeof param : string
>param : string | number
>param.length : number
>param : string
>length : number
// local
var var3: string | number;
>var3 : string | number
num = typeof var3 === "string" && var3.length; // string
>num = typeof var3 === "string" && var3.length : number
>num : number
>typeof var3 === "string" && var3.length : number
>typeof var3 === "string" : boolean
>typeof var3 : string
>var3 : string | number
>var3.length : number
>var3 : string
>length : number
num = typeof param1 === "string" && param1.length; // string
>num = typeof param1 === "string" && param1.length : number
>num : number
>typeof param1 === "string" && param1.length : number
>typeof param1 === "string" : boolean
>typeof param1 : string
>param1 : string | number
>param1.length : number
>param1 : string
>length : number
} (param);
>param : string | number
}
// Arrow expression
function f3(param: string | number) {
>f3 : (param: string | number) => void
>param : string | number
// variables in function declaration
var var2: string | number;
>var2 : string | number
// variables in function expressions
var r = ((param1: string | number) => {
>r : void
>((param1: string | number) => { // global vars in function declaration num = typeof var1 === "string" && var1.length; // string // variables from outer function declaration num = typeof var2 === "string" && var2.length; // string // parameters in outer declaration num = typeof param === "string" && param.length; // string // local var var3: string | number; num = typeof var3 === "string" && var3.length; // string num = typeof param1 === "string" && param1.length; // string })(param) : void
>((param1: string | number) => { // global vars in function declaration num = typeof var1 === "string" && var1.length; // string // variables from outer function declaration num = typeof var2 === "string" && var2.length; // string // parameters in outer declaration num = typeof param === "string" && param.length; // string // local var var3: string | number; num = typeof var3 === "string" && var3.length; // string num = typeof param1 === "string" && param1.length; // string }) : (param1: string | number) => void
>(param1: string | number) => { // global vars in function declaration num = typeof var1 === "string" && var1.length; // string // variables from outer function declaration num = typeof var2 === "string" && var2.length; // string // parameters in outer declaration num = typeof param === "string" && param.length; // string // local var var3: string | number; num = typeof var3 === "string" && var3.length; // string num = typeof param1 === "string" && param1.length; // string } : (param1: string | number) => void
>param1 : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// variables from outer function declaration
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
// parameters in outer declaration
num = typeof param === "string" && param.length; // string
>num = typeof param === "string" && param.length : number
>num : number
>typeof param === "string" && param.length : number
>typeof param === "string" : boolean
>typeof param : string
>param : string | number
>param.length : number
>param : string
>length : number
// local
var var3: string | number;
>var3 : string | number
num = typeof var3 === "string" && var3.length; // string
>num = typeof var3 === "string" && var3.length : number
>num : number
>typeof var3 === "string" && var3.length : number
>typeof var3 === "string" : boolean
>typeof var3 : string
>var3 : string | number
>var3.length : number
>var3 : string
>length : number
num = typeof param1 === "string" && param1.length; // string
>num = typeof param1 === "string" && param1.length : number
>num : number
>typeof param1 === "string" && param1.length : number
>typeof param1 === "string" : boolean
>typeof param1 : string
>param1 : string | number
>param1.length : number
>param1 : string
>length : number
})(param);
>param : string | number
}
// Return type of function
// Inside function declaration
var strOrNum: string | number;
>strOrNum : string | number
function f4() {
>f4 : () => string | number
var var2: string | number = strOrNum;
>var2 : string | number
>strOrNum : string | number
return var2;
>var2 : string | number
}
strOrNum = typeof f4() === "string" && f4(); // string | number
>strOrNum = typeof f4() === "string" && f4() : string | number
>strOrNum : string | number
>typeof f4() === "string" && f4() : string | number
>typeof f4() === "string" : boolean
>typeof f4() : string
>f4() : string | number
>f4 : () => string | number
>f4() : string | number
>f4 : () => string | number

View File

@@ -0,0 +1,131 @@
//// [typeGuardsInFunctionAndModuleBlock.ts]
// typeguards are scoped in function/module block
function foo(x: number | string | boolean) {
return typeof x === "string"
? x
: function f() {
var b = x; // new scope - number | boolean | string
return typeof x === "boolean"
? x.toString() // boolean
: x.toString(); // number | string
} ();
}
function foo2(x: number | string | boolean) {
return typeof x === "string"
? x
: function f(a: number | boolean) {
var b = x; // new scope - number | boolean | string
return typeof x === "boolean"
? x.toString() // boolean
: x.toString(); // number | string
} (x); // x here is narrowed to number | boolean
}
function foo3(x: number | string | boolean) {
return typeof x === "string"
? x
: (() => {
var b = x; // new scope - number | boolean | string
return typeof x === "boolean"
? x.toString() // boolean
: x.toString(); // number | string
})();
}
function foo4(x: number | string | boolean) {
return typeof x === "string"
? x
: ((a: number | boolean) => {
var b = x; // new scope - number | boolean | string
return typeof x === "boolean"
? x.toString() // boolean
: x.toString(); // number | string
})(x); // x here is narrowed to number | boolean
}
module m {
var x: number | string | boolean;
module m2 {
var b = x; // new scope - number | boolean | string
var y: string;
if (typeof x === "string") {
y = x // string;
} else {
y = typeof x === "boolean"
? x.toString() // boolean
: x.toString(); // number
}
}
}
module m1 {
var x: number | string | boolean;
module m2.m3 {
var b = x; // new scope - number | boolean | string
var y: string;
if (typeof x === "string") {
y = x // string;
} else {
y = typeof x === "boolean"
? x.toString() // boolean
: x.toString(); // number
}
}
}
//// [typeGuardsInFunctionAndModuleBlock.js]
// typeguards are scoped in function/module block
function foo(x) {
return typeof x === "string" ? x : function f() {
var b = x; // new scope - number | boolean | string
return typeof x === "boolean" ? x.toString() : x.toString(); // number | string
}();
}
function foo2(x) {
return typeof x === "string" ? x : function f(a) {
var b = x; // new scope - number | boolean | string
return typeof x === "boolean" ? x.toString() : x.toString(); // number | string
}(x); // x here is narrowed to number | boolean
}
function foo3(x) {
return typeof x === "string" ? x : (function () {
var b = x; // new scope - number | boolean | string
return typeof x === "boolean" ? x.toString() : x.toString(); // number | string
})();
}
function foo4(x) {
return typeof x === "string" ? x : (function (a) {
var b = x; // new scope - number | boolean | string
return typeof x === "boolean" ? x.toString() : x.toString(); // number | string
})(x); // x here is narrowed to number | boolean
}
var m;
(function (m) {
var x;
var m2;
(function (m2) {
var b = x; // new scope - number | boolean | string
var y;
if (typeof x === "string") {
y = x; // string;
}
else {
y = typeof x === "boolean" ? x.toString() : x.toString(); // number
}
})(m2 || (m2 = {}));
})(m || (m = {}));
var m1;
(function (m1) {
var x;
var m2;
(function (m2) {
var m3;
(function (m3) {
var b = x; // new scope - number | boolean | string
var y;
if (typeof x === "string") {
y = x; // string;
}
else {
y = typeof x === "boolean" ? x.toString() : x.toString(); // number
}
})(m3 = m2.m3 || (m2.m3 = {}));
})(m2 || (m2 = {}));
})(m1 || (m1 = {}));

View File

@@ -0,0 +1,274 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInFunctionAndModuleBlock.ts ===
// typeguards are scoped in function/module block
function foo(x: number | string | boolean) {
>foo : (x: string | number | boolean) => string
>x : string | number | boolean
return typeof x === "string"
>typeof x === "string" ? x : function f() { var b = x; // new scope - number | boolean | string return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number | string } () : string
>typeof x === "string" : boolean
>typeof x : string
>x : string | number | boolean
? x
>x : string
: function f() {
>function f() { var b = x; // new scope - number | boolean | string return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number | string } () : string
>function f() { var b = x; // new scope - number | boolean | string return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number | string } : () => string
>f : () => string
var b = x; // new scope - number | boolean | string
>b : string | number | boolean
>x : string | number | boolean
return typeof x === "boolean"
>typeof x === "boolean" ? x.toString() // boolean : x.toString() : string
>typeof x === "boolean" : boolean
>typeof x : string
>x : string | number | boolean
? x.toString() // boolean
>x.toString() : string
>x.toString : () => string
>x : boolean
>toString : () => string
: x.toString(); // number | string
>x.toString() : string
>x.toString : () => string
>x : string | number
>toString : () => string
} ();
}
function foo2(x: number | string | boolean) {
>foo2 : (x: string | number | boolean) => string
>x : string | number | boolean
return typeof x === "string"
>typeof x === "string" ? x : function f(a: number | boolean) { var b = x; // new scope - number | boolean | string return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number | string } (x) : string
>typeof x === "string" : boolean
>typeof x : string
>x : string | number | boolean
? x
>x : string
: function f(a: number | boolean) {
>function f(a: number | boolean) { var b = x; // new scope - number | boolean | string return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number | string } (x) : string
>function f(a: number | boolean) { var b = x; // new scope - number | boolean | string return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number | string } : (a: number | boolean) => string
>f : (a: number | boolean) => string
>a : number | boolean
var b = x; // new scope - number | boolean | string
>b : string | number | boolean
>x : string | number | boolean
return typeof x === "boolean"
>typeof x === "boolean" ? x.toString() // boolean : x.toString() : string
>typeof x === "boolean" : boolean
>typeof x : string
>x : string | number | boolean
? x.toString() // boolean
>x.toString() : string
>x.toString : () => string
>x : boolean
>toString : () => string
: x.toString(); // number | string
>x.toString() : string
>x.toString : () => string
>x : string | number
>toString : () => string
} (x); // x here is narrowed to number | boolean
>x : number | boolean
}
function foo3(x: number | string | boolean) {
>foo3 : (x: string | number | boolean) => string
>x : string | number | boolean
return typeof x === "string"
>typeof x === "string" ? x : (() => { var b = x; // new scope - number | boolean | string return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number | string })() : string
>typeof x === "string" : boolean
>typeof x : string
>x : string | number | boolean
? x
>x : string
: (() => {
>(() => { var b = x; // new scope - number | boolean | string return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number | string })() : string
>(() => { var b = x; // new scope - number | boolean | string return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number | string }) : () => string
>() => { var b = x; // new scope - number | boolean | string return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number | string } : () => string
var b = x; // new scope - number | boolean | string
>b : string | number | boolean
>x : string | number | boolean
return typeof x === "boolean"
>typeof x === "boolean" ? x.toString() // boolean : x.toString() : string
>typeof x === "boolean" : boolean
>typeof x : string
>x : string | number | boolean
? x.toString() // boolean
>x.toString() : string
>x.toString : () => string
>x : boolean
>toString : () => string
: x.toString(); // number | string
>x.toString() : string
>x.toString : () => string
>x : string | number
>toString : () => string
})();
}
function foo4(x: number | string | boolean) {
>foo4 : (x: string | number | boolean) => string
>x : string | number | boolean
return typeof x === "string"
>typeof x === "string" ? x : ((a: number | boolean) => { var b = x; // new scope - number | boolean | string return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number | string })(x) : string
>typeof x === "string" : boolean
>typeof x : string
>x : string | number | boolean
? x
>x : string
: ((a: number | boolean) => {
>((a: number | boolean) => { var b = x; // new scope - number | boolean | string return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number | string })(x) : string
>((a: number | boolean) => { var b = x; // new scope - number | boolean | string return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number | string }) : (a: number | boolean) => string
>(a: number | boolean) => { var b = x; // new scope - number | boolean | string return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number | string } : (a: number | boolean) => string
>a : number | boolean
var b = x; // new scope - number | boolean | string
>b : string | number | boolean
>x : string | number | boolean
return typeof x === "boolean"
>typeof x === "boolean" ? x.toString() // boolean : x.toString() : string
>typeof x === "boolean" : boolean
>typeof x : string
>x : string | number | boolean
? x.toString() // boolean
>x.toString() : string
>x.toString : () => string
>x : boolean
>toString : () => string
: x.toString(); // number | string
>x.toString() : string
>x.toString : () => string
>x : string | number
>toString : () => string
})(x); // x here is narrowed to number | boolean
>x : number | boolean
}
module m {
>m : typeof m
var x: number | string | boolean;
>x : string | number | boolean
module m2 {
>m2 : typeof m2
var b = x; // new scope - number | boolean | string
>b : string | number | boolean
>x : string | number | boolean
var y: string;
>y : string
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : string | number | boolean
y = x // string;
>y = x : string
>y : string
>x : string
} else {
y = typeof x === "boolean"
>y = typeof x === "boolean" ? x.toString() // boolean : x.toString() : string
>y : string
>typeof x === "boolean" ? x.toString() // boolean : x.toString() : string
>typeof x === "boolean" : boolean
>typeof x : string
>x : number | boolean
? x.toString() // boolean
>x.toString() : string
>x.toString : () => string
>x : boolean
>toString : () => string
: x.toString(); // number
>x.toString() : string
>x.toString : (radix?: number) => string
>x : number
>toString : (radix?: number) => string
}
}
}
module m1 {
>m1 : typeof m1
var x: number | string | boolean;
>x : string | number | boolean
module m2.m3 {
>m2 : typeof m2
>m3 : typeof m3
var b = x; // new scope - number | boolean | string
>b : string | number | boolean
>x : string | number | boolean
var y: string;
>y : string
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : string | number | boolean
y = x // string;
>y = x : string
>y : string
>x : string
} else {
y = typeof x === "boolean"
>y = typeof x === "boolean" ? x.toString() // boolean : x.toString() : string
>y : string
>typeof x === "boolean" ? x.toString() // boolean : x.toString() : string
>typeof x === "boolean" : boolean
>typeof x : string
>x : number | boolean
? x.toString() // boolean
>x.toString() : string
>x.toString : () => string
>x : boolean
>toString : () => string
: x.toString(); // number
>x.toString() : string
>x.toString : (radix?: number) => string
>x : number
>toString : (radix?: number) => string
}
}
}

View File

@@ -0,0 +1,27 @@
//// [typeGuardsInGlobal.ts]
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num: number;
var var1: string | number;
if (typeof var1 === "string") {
num = var1.length; // string
}
else {
num = var1; // number
}
//// [typeGuardsInGlobal.js]
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num;
var var1;
if (typeof var1 === "string") {
num = var1.length; // string
}
else {
num = var1; // number
}

View File

@@ -0,0 +1,30 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInGlobal.ts ===
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num: number;
>num : number
var var1: string | number;
>var1 : string | number
if (typeof var1 === "string") {
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
num = var1.length; // string
>num = var1.length : number
>num : number
>var1.length : number
>var1 : string
>length : number
}
else {
num = var1; // number
>num = var1 : number
>num : number
>var1 : number
}

View File

@@ -0,0 +1,287 @@
//// [typeGuardsInIfStatement.ts]
// In the true branch statement of an <20>if<69> statement,
// the type of a variable or parameter is narrowed by any type guard in the <20>if<69> condition when true,
// provided the true branch statement contains no assignments to the variable or parameter.
// In the false branch statement of an <20>if<69> statement,
// the type of a variable or parameter is narrowed by any type guard in the <20>if<69> condition when false,
// provided the false branch statement contains no assignments to the variable or parameter
function foo(x: number | string) {
if (typeof x === "string") {
return x.length; // string
}
else {
return x++; // number
}
}
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
}
else {
return x; // string | 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
}
else {
return x; // string | 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
}
else {
x = 10; // even though assigned number - this should result in x to be string | number
return x; // string | 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
}
else {
x = "hello";
return x; // string | number
}
}
function foo6(x: number | string) {
// Modify in both branches
if (typeof x === "string") {
x = 10;
return x; // string | number
}
else {
x = "hello";
return x; // string | number
}
}
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
}
}
//// [typeGuardsInIfStatement.js]
// In the true branch statement of an <20>if<69> statement,
// the type of a variable or parameter is narrowed by any type guard in the <20>if<69> condition when true,
// provided the true branch statement contains no assignments to the variable or parameter.
// In the false branch statement of an <20>if<69> statement,
// the type of a variable or parameter is narrowed by any type guard in the <20>if<69> condition when false,
// provided the false branch statement contains no assignments to the variable or parameter
function foo(x) {
if (typeof x === "string") {
return x.length; // string
}
else {
return x++; // number
}
}
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
}
else {
return x; // string | 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
}
else {
return x; // string | number
}
}
function foo4(x) {
// false branch updates the variable - so here it is not number
if (typeof x === "string") {
return x; // string | number
}
else {
x = 10; // even though assigned number - this should result in x to be string | number
return x; // string | number
}
}
function foo5(x) {
// false branch updates the variable - so here it is not number
if (typeof x === "string") {
return x; // string | number
}
else {
x = "hello";
return x; // string | number
}
}
function foo6(x) {
// Modify in both branches
if (typeof x === "string") {
x = 10;
return x; // string | number
}
else {
x = "hello";
return x; // string | number
}
}
function foo7(x) {
if (typeof x === "string") {
return x === "hello"; // string
}
else if (typeof x === "boolean") {
return x; // boolean
}
else {
return x == 10; // number
}
}
function foo8(x) {
if (typeof x === "string") {
return x === "hello"; // string
}
else {
var b = x; // number | boolean
if (typeof x === "boolean") {
return x; // boolean
}
else {
return x == 10; // number
}
}
}
function foo9(x) {
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) {
// Mixing typeguard narrowing in if statement with conditional expression typeguard
if (typeof x === "string") {
return x === "hello"; // string
}
else {
var y;
var b = x; // number | boolean
return typeof x === "number" ? x === 10 : x; // x should be boolean
}
}
function foo11(x) {
// 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;
var b = x; // number | boolean | string - because below we are changing value of x in if statement
return typeof x === "number" ? (x = 10 && x.toString()) : (y = x && x.toString());
}
}
function foo12(x) {
// 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() : x.toString(); // boolean | string
}
}

View File

@@ -0,0 +1,371 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInIfStatement.ts ===
// In the true branch statement of an <20>if<69> statement,
// the type of a variable or parameter is narrowed by any type guard in the <20>if<69> condition when true,
// provided the true branch statement contains no assignments to the variable or parameter.
// In the false branch statement of an <20>if<69> statement,
// the type of a variable or parameter is narrowed by any type guard in the <20>if<69> condition when false,
// provided the false branch statement contains no assignments to the variable or parameter
function foo(x: number | string) {
>foo : (x: string | number) => number
>x : string | number
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
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: string | number) => string | number
>x : string | number
// 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 : string | number
x = 10;
>x = 10 : number
>x : string | number
return x; // string | number
>x : string | number
}
else {
return x; // string | number
>x : string | number
}
}
function foo3(x: number | string) {
>foo3 : (x: string | number) => string | number
>x : string | number
// 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 : string | number
x = "Hello"; // even though assigned using same type as narrowed expression
>x = "Hello" : string
>x : string | number
return x; // string | number
>x : string | number
}
else {
return x; // string | number
>x : string | number
}
}
function foo4(x: number | string) {
>foo4 : (x: string | number) => string | number
>x : string | number
// false branch updates the variable - so here it is not number
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
return x; // string | number
>x : string | number
}
else {
x = 10; // even though assigned number - this should result in x to be string | number
>x = 10 : number
>x : string | number
return x; // string | number
>x : string | number
}
}
function foo5(x: number | string) {
>foo5 : (x: string | number) => string | number
>x : string | number
// false branch updates the variable - so here it is not number
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
return x; // string | number
>x : string | number
}
else {
x = "hello";
>x = "hello" : string
>x : string | number
return x; // string | number
>x : string | number
}
}
function foo6(x: number | string) {
>foo6 : (x: string | number) => string | number
>x : string | number
// Modify in both branches
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
x = 10;
>x = 10 : number
>x : string | number
return x; // string | number
>x : string | number
}
else {
x = "hello";
>x = "hello" : string
>x : string | number
return x; // string | number
>x : string | number
}
}
function foo7(x: number | string | boolean) {
>foo7 : (x: string | number | boolean) => boolean
>x : string | number | boolean
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : string | number | boolean
return x === "hello"; // string
>x === "hello" : boolean
>x : string
}
else if (typeof x === "boolean") {
>typeof x === "boolean" : boolean
>typeof x : string
>x : number | boolean
return x; // boolean
>x : boolean
}
else {
return x == 10; // number
>x == 10 : boolean
>x : number
}
}
function foo8(x: number | string | boolean) {
>foo8 : (x: string | number | boolean) => boolean
>x : string | number | boolean
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : string | number | boolean
return x === "hello"; // string
>x === "hello" : boolean
>x : 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
return x; // boolean
>x : boolean
}
else {
return x == 10; // number
>x == 10 : boolean
>x : number
}
}
}
function foo9(x: number | string) {
>foo9 : (x: string | number) => boolean
>x : string | number
var y = 10;
>y : number
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
// 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
}
else {
return x == 10; // number
>x == 10 : boolean
>x : number
}
}
function foo10(x: number | string | boolean) {
>foo10 : (x: string | number | boolean) => boolean
>x : string | number | boolean
// Mixing typeguard narrowing in if statement with conditional expression typeguard
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : string | number | boolean
return x === "hello"; // string
>x === "hello" : boolean
>x : string
}
else {
var y: boolean | string;
>y : string | boolean
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
? x === 10 // number
>x === 10 : boolean
>x : number
: x; // x should be boolean
>x : boolean
}
}
function foo11(x: number | string | boolean) {
>foo11 : (x: string | number | boolean) => string | number | boolean
>x : string | number | 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 : string | number | boolean
return x; // string | number | boolean - x changed in else branch
>x : string | number | boolean
}
else {
var y: number| boolean | string;
>y : string | number | boolean
var b = x; // number | boolean | string - because below we are changing value of x in if statement
>b : string | number | boolean
>x : string | number | 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 : string | number | boolean
? (
>( // 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 : string | number | boolean
>10 && x.toString() : string
>x.toString() : string
>x.toString : () => string
>x : string | number | boolean
>toString : () => 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 : string | number | boolean
>x && x.toString() : string
>x : string | number | boolean
>x.toString() : string
>x.toString : () => string
>x : string | number | boolean
>toString : () => string
);
}
}
function foo12(x: number | string | boolean) {
>foo12 : (x: string | number | boolean) => string
>x : string | number | 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 : string | number | boolean
return x.toString(); // string | number | boolean - x changed in else branch
>x.toString() : string
>x.toString : () => string
>x : string | number | boolean
>toString : () => string
}
else {
x = 10;
>x = 10 : number
>x : string | number | boolean
var b = x; // number | boolean | string
>b : string | number | boolean
>x : string | number | boolean
return typeof x === "number"
>typeof x === "number" ? x.toString() // number : x.toString() : string
>typeof x === "number" : boolean
>typeof x : string
>x : string | number | boolean
? 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
}
}

View File

@@ -0,0 +1,174 @@
//// [typeGuardsInModule.ts]
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num: number;
var strOrNum: string | number;
var var1: string | number;
// Inside module
module m1 {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in module declaration
var var2: string | number;
if (typeof var2 === "string") {
num = var2.length; // string
}
else {
num = var2; // number
}
// exported variable in the module
export var var3: string | number;
if (typeof var3 === "string") {
strOrNum = var3; // string | number
}
else {
strOrNum = var3; // string | number
}
}
// local module
module m2 {
var var2: string | number;
export var var3: string | number;
module m3 {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// local variables from outer module declaration
num = typeof var2 === "string" && var2.length; // string
// exported variable from outer the module
strOrNum = typeof var3 === "string" && var3; // string | number
// variables in module declaration
var var4: string | number;
if (typeof var4 === "string") {
num = var4.length; // string
}
else {
num = var4; // number
}
// exported variable in the module
export var var5: string | number;
if (typeof var5 === "string") {
strOrNum = var5; // string | number
}
else {
strOrNum = var5; // string | number
}
}
}
// Dotted module
module m3.m4 {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in module declaration
var var2: string | number;
if (typeof var2 === "string") {
num = var2.length; // string
}
else {
num = var2; // number
}
// exported variable in the module
export var var3: string | number;
if (typeof var3 === "string") {
strOrNum = var3; // string | number
}
else {
strOrNum = var3; // string | number
}
}
//// [typeGuardsInModule.js]
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num;
var strOrNum;
var var1;
// Inside module
var m1;
(function (m1) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in module declaration
var var2;
if (typeof var2 === "string") {
num = var2.length; // string
}
else {
num = var2; // number
}
// exported variable in the module
m1.var3;
if (typeof m1.var3 === "string") {
strOrNum = m1.var3; // string | number
}
else {
strOrNum = m1.var3; // string | number
}
})(m1 || (m1 = {}));
// local module
var m2;
(function (m2) {
var var2;
m2.var3;
var m3;
(function (m3) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// local variables from outer module declaration
num = typeof var2 === "string" && var2.length; // string
// exported variable from outer the module
strOrNum = typeof m2.var3 === "string" && m2.var3; // string | number
// variables in module declaration
var var4;
if (typeof var4 === "string") {
num = var4.length; // string
}
else {
num = var4; // number
}
// exported variable in the module
m3.var5;
if (typeof m3.var5 === "string") {
strOrNum = m3.var5; // string | number
}
else {
strOrNum = m3.var5; // string | number
}
})(m3 || (m3 = {}));
})(m2 || (m2 = {}));
// Dotted module
var m3;
(function (m3) {
var m4;
(function (m4) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in module declaration
var var2;
if (typeof var2 === "string") {
num = var2.length; // string
}
else {
num = var2; // number
}
// exported variable in the module
m4.var3;
if (typeof m4.var3 === "string") {
strOrNum = m4.var3; // string | number
}
else {
strOrNum = m4.var3; // string | number
}
})(m4 = m3.m4 || (m3.m4 = {}));
})(m3 || (m3 = {}));

View File

@@ -0,0 +1,228 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInModule.ts ===
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num: number;
>num : number
var strOrNum: string | number;
>strOrNum : string | number
var var1: string | number;
>var1 : string | number
// Inside module
module m1 {
>m1 : typeof m1
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// variables in module declaration
var var2: string | number;
>var2 : string | number
if (typeof var2 === "string") {
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
num = var2.length; // string
>num = var2.length : number
>num : number
>var2.length : number
>var2 : string
>length : number
}
else {
num = var2; // number
>num = var2 : number
>num : number
>var2 : number
}
// exported variable in the module
export var var3: string | number;
>var3 : string | number
if (typeof var3 === "string") {
>typeof var3 === "string" : boolean
>typeof var3 : string
>var3 : string | number
strOrNum = var3; // string | number
>strOrNum = var3 : string | number
>strOrNum : string | number
>var3 : string | number
}
else {
strOrNum = var3; // string | number
>strOrNum = var3 : string | number
>strOrNum : string | number
>var3 : string | number
}
}
// local module
module m2 {
>m2 : typeof m2
var var2: string | number;
>var2 : string | number
export var var3: string | number;
>var3 : string | number
module m3 {
>m3 : typeof m3
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// local variables from outer module declaration
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
// exported variable from outer the module
strOrNum = typeof var3 === "string" && var3; // string | number
>strOrNum = typeof var3 === "string" && var3 : string | number
>strOrNum : string | number
>typeof var3 === "string" && var3 : string | number
>typeof var3 === "string" : boolean
>typeof var3 : string
>var3 : string | number
>var3 : string | number
// variables in module declaration
var var4: string | number;
>var4 : string | number
if (typeof var4 === "string") {
>typeof var4 === "string" : boolean
>typeof var4 : string
>var4 : string | number
num = var4.length; // string
>num = var4.length : number
>num : number
>var4.length : number
>var4 : string
>length : number
}
else {
num = var4; // number
>num = var4 : number
>num : number
>var4 : number
}
// exported variable in the module
export var var5: string | number;
>var5 : string | number
if (typeof var5 === "string") {
>typeof var5 === "string" : boolean
>typeof var5 : string
>var5 : string | number
strOrNum = var5; // string | number
>strOrNum = var5 : string | number
>strOrNum : string | number
>var5 : string | number
}
else {
strOrNum = var5; // string | number
>strOrNum = var5 : string | number
>strOrNum : string | number
>var5 : string | number
}
}
}
// Dotted module
module m3.m4 {
>m3 : typeof m3
>m4 : typeof m4
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// variables in module declaration
var var2: string | number;
>var2 : string | number
if (typeof var2 === "string") {
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
num = var2.length; // string
>num = var2.length : number
>num : number
>var2.length : number
>var2 : string
>length : number
}
else {
num = var2; // number
>num = var2 : number
>num : number
>var2 : number
}
// exported variable in the module
export var var3: string | number;
>var3 : string | number
if (typeof var3 === "string") {
>typeof var3 === "string" : boolean
>typeof var3 : string
>var3 : string | number
strOrNum = var3; // string | number
>strOrNum = var3 : string | number
>strOrNum : string | number
>var3 : string | number
}
else {
strOrNum = var3; // string | number
>strOrNum = var3 : string | number
>strOrNum : string | number
>var3 : string | number
}
}

View File

@@ -0,0 +1,56 @@
//// [typeGuardsInProperties.ts]
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
var num: number;
var strOrNum: string | number;
class C1 {
private pp1: string | number;
pp2: string | number;
// Inside public accessor getter
get pp3() {
return strOrNum;
}
method() {
strOrNum = typeof this.pp1 === "string" && this.pp1; // string | number
strOrNum = typeof this.pp2 === "string" && this.pp2; // string | number
strOrNum = typeof this.pp3 === "string" && this.pp3; // string | number
}
}
var c1: C1;
strOrNum = typeof c1.pp2 === "string" && c1.pp2; // string | number
strOrNum = typeof c1.pp3 === "string" && c1.pp3; // string | number
var obj1: {
x: string | number;
};
strOrNum = typeof obj1.x === "string" && obj1.x; // string | number
//// [typeGuardsInProperties.js]
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
var num;
var strOrNum;
var C1 = (function () {
function C1() {
}
Object.defineProperty(C1.prototype, "pp3", {
// Inside public accessor getter
get: function () {
return strOrNum;
},
enumerable: true,
configurable: true
});
C1.prototype.method = function () {
strOrNum = typeof this.pp1 === "string" && this.pp1; // string | number
strOrNum = typeof this.pp2 === "string" && this.pp2; // string | number
strOrNum = typeof this.pp3 === "string" && this.pp3; // string | number
};
return C1;
})();
var c1;
strOrNum = typeof c1.pp2 === "string" && c1.pp2; // string | number
strOrNum = typeof c1.pp3 === "string" && c1.pp3; // string | number
var obj1;
strOrNum = typeof obj1.x === "string" && obj1.x; // string | number

View File

@@ -0,0 +1,120 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInProperties.ts ===
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
var num: number;
>num : number
var strOrNum: string | number;
>strOrNum : string | number
class C1 {
>C1 : C1
private pp1: string | number;
>pp1 : string | number
pp2: string | number;
>pp2 : string | number
// Inside public accessor getter
get pp3() {
>pp3 : string | number
return strOrNum;
>strOrNum : string | number
}
method() {
>method : () => void
strOrNum = typeof this.pp1 === "string" && this.pp1; // string | number
>strOrNum = typeof this.pp1 === "string" && this.pp1 : string | number
>strOrNum : string | number
>typeof this.pp1 === "string" && this.pp1 : string | number
>typeof this.pp1 === "string" : boolean
>typeof this.pp1 : string
>this.pp1 : string | number
>this : C1
>pp1 : string | number
>this.pp1 : string | number
>this : C1
>pp1 : string | number
strOrNum = typeof this.pp2 === "string" && this.pp2; // string | number
>strOrNum = typeof this.pp2 === "string" && this.pp2 : string | number
>strOrNum : string | number
>typeof this.pp2 === "string" && this.pp2 : string | number
>typeof this.pp2 === "string" : boolean
>typeof this.pp2 : string
>this.pp2 : string | number
>this : C1
>pp2 : string | number
>this.pp2 : string | number
>this : C1
>pp2 : string | number
strOrNum = typeof this.pp3 === "string" && this.pp3; // string | number
>strOrNum = typeof this.pp3 === "string" && this.pp3 : string | number
>strOrNum : string | number
>typeof this.pp3 === "string" && this.pp3 : string | number
>typeof this.pp3 === "string" : boolean
>typeof this.pp3 : string
>this.pp3 : string | number
>this : C1
>pp3 : string | number
>this.pp3 : string | number
>this : C1
>pp3 : string | number
}
}
var c1: C1;
>c1 : C1
>C1 : C1
strOrNum = typeof c1.pp2 === "string" && c1.pp2; // string | number
>strOrNum = typeof c1.pp2 === "string" && c1.pp2 : string | number
>strOrNum : string | number
>typeof c1.pp2 === "string" && c1.pp2 : string | number
>typeof c1.pp2 === "string" : boolean
>typeof c1.pp2 : string
>c1.pp2 : string | number
>c1 : C1
>pp2 : string | number
>c1.pp2 : string | number
>c1 : C1
>pp2 : string | number
strOrNum = typeof c1.pp3 === "string" && c1.pp3; // string | number
>strOrNum = typeof c1.pp3 === "string" && c1.pp3 : string | number
>strOrNum : string | number
>typeof c1.pp3 === "string" && c1.pp3 : string | number
>typeof c1.pp3 === "string" : boolean
>typeof c1.pp3 : string
>c1.pp3 : string | number
>c1 : C1
>pp3 : string | number
>c1.pp3 : string | number
>c1 : C1
>pp3 : string | number
var obj1: {
>obj1 : { x: string | number; }
x: string | number;
>x : string | number
};
strOrNum = typeof obj1.x === "string" && obj1.x; // string | number
>strOrNum = typeof obj1.x === "string" && obj1.x : string | number
>strOrNum : string | number
>typeof obj1.x === "string" && obj1.x : string | number
>typeof obj1.x === "string" : boolean
>typeof obj1.x : string
>obj1.x : string | number
>obj1 : { x: string | number; }
>x : string | number
>obj1.x : string | number
>obj1 : { x: string | number; }
>x : string | number

View File

@@ -0,0 +1,96 @@
//// [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.
function foo(x: number | string) {
return typeof x === "string" && x.length === 10; // string
}
function foo2(x: number | string) {
// modify x in right hand operand
return typeof x === "string" && ((x = 10) && x); // string | number
}
function foo3(x: number | string) {
// modify x in right hand operand with string type itself
return typeof x === "string" && ((x = "hello") && x); // string | number
}
function foo4(x: number | string | boolean) {
return typeof x !== "string" // string | number | boolean
&& typeof x !== "number" // number | boolean
&& x; // boolean
}
function foo5(x: number | string | boolean) {
// usage of x or assignment to separate variable shouldn't cause narrowing of type to stop
var b: number | boolean;
return typeof x !== "string" // string | number | boolean
&& ((b = x) && (typeof x !== "number" // number | boolean
&& x)); // boolean
}
function foo6(x: number | string | boolean) {
// Mixing typeguard narrowing in if statement with conditional expression typeguard
return typeof x !== "string" // string | number | boolean
&& (typeof x !== "number" // number | boolean
? x // boolean
: x === 10) // number
}
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
&& (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 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.
function foo(x) {
return typeof x === "string" && x.length === 10; // string
}
function foo2(x) {
// modify x in right hand operand
return typeof x === "string" && ((x = 10) && x); // string | number
}
function foo3(x) {
// modify x in right hand operand with string type itself
return typeof x === "string" && ((x = "hello") && x); // string | number
}
function foo4(x) {
return typeof x !== "string" && typeof x !== "number" && x; // boolean
}
function foo5(x) {
// usage of x or assignment to separate variable shouldn't cause narrowing of type to stop
var b;
return typeof x !== "string" && ((b = x) && (typeof x !== "number" && x)); // boolean
}
function foo6(x) {
// Mixing typeguard narrowing in if statement with conditional expression typeguard
return typeof x !== "string" && (typeof x !== "number" ? x : x === 10); // number
}
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) && (typeof x === "number" ? (x = 10 && x.toString()) : (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) && (typeof x === "number" ? x : x.length); // string
}

View File

@@ -0,0 +1,215 @@
=== 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.
function foo(x: number | string) {
>foo : (x: string | number) => boolean
>x : string | number
return typeof x === "string" && x.length === 10; // string
>typeof x === "string" && x.length === 10 : boolean
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
>x.length === 10 : boolean
>x.length : number
>x : string
>length : number
}
function foo2(x: number | string) {
>foo2 : (x: string | number) => string | number
>x : string | number
// modify x in right hand operand
return typeof x === "string" && ((x = 10) && x); // string | number
>typeof x === "string" && ((x = 10) && x) : string | number
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
>((x = 10) && x) : string | number
>(x = 10) && x : string | number
>(x = 10) : number
>x = 10 : number
>x : string | number
>x : string | number
}
function foo3(x: number | string) {
>foo3 : (x: string | number) => string | number
>x : string | number
// 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) : string | number
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
>((x = "hello") && x) : string | number
>(x = "hello") && x : string | number
>(x = "hello") : string
>x = "hello" : string
>x : string | number
>x : string | number
}
function foo4(x: number | string | boolean) {
>foo4 : (x: string | number | boolean) => boolean
>x : string | number | boolean
return typeof x !== "string" // string | number | boolean
>typeof x !== "string" // string | number | boolean && typeof x !== "number" // number | boolean && x : boolean
>typeof x !== "string" // string | number | boolean && typeof x !== "number" : boolean
>typeof x !== "string" : boolean
>typeof x : string
>x : string | number | boolean
&& typeof x !== "number" // number | boolean
>typeof x !== "number" : boolean
>typeof x : string
>x : number | boolean
&& x; // boolean
>x : boolean
}
function foo5(x: number | string | boolean) {
>foo5 : (x: string | number | boolean) => boolean
>x : string | number | boolean
// usage of x or assignment to separate variable shouldn't cause narrowing of type to stop
var b: number | boolean;
>b : number | boolean
return typeof x !== "string" // string | number | boolean
>typeof x !== "string" // string | number | boolean && ((b = x) && (typeof x !== "number" // number | boolean && x)) : boolean
>typeof x !== "string" : boolean
>typeof x : string
>x : string | number | boolean
&& ((b = x) && (typeof x !== "number" // number | boolean
>((b = x) && (typeof x !== "number" // number | boolean && x)) : boolean
>(b = x) && (typeof x !== "number" // number | boolean && x) : boolean
>(b = x) : number | boolean
>b = x : number | boolean
>b : number | boolean
>x : number | boolean
>(typeof x !== "number" // number | boolean && x) : boolean
>typeof x !== "number" // number | boolean && x : boolean
>typeof x !== "number" : boolean
>typeof x : string
>x : number | boolean
&& x)); // boolean
>x : boolean
}
function foo6(x: number | string | boolean) {
>foo6 : (x: string | number | boolean) => boolean
>x : string | number | boolean
// Mixing typeguard narrowing in if statement with conditional expression typeguard
return typeof x !== "string" // string | number | boolean
>typeof x !== "string" // string | number | boolean && (typeof x !== "number" // number | boolean ? x // boolean : x === 10) : boolean
>typeof x !== "string" : boolean
>typeof x : string
>x : string | number | boolean
&& (typeof x !== "number" // number | boolean
>(typeof x !== "number" // number | boolean ? x // boolean : x === 10) : boolean
>typeof x !== "number" // number | boolean ? x // boolean : x === 10 : boolean
>typeof x !== "number" : boolean
>typeof x : string
>x : number | boolean
? x // boolean
>x : boolean
: x === 10) // number
>x === 10 : boolean
>x : number
}
function foo7(x: number | string | boolean) {
>foo7 : (x: string | number | boolean) => string
>x : string | number | boolean
var y: number| boolean | string;
>y : string | number | boolean
var z: number| boolean | string;
>z : string | number | boolean
// 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" : boolean
>typeof x : string
>x : string | number | boolean
&& ((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) : string | number | boolean
>z = x : string | number | boolean
>z : string | number | boolean
>x : string | 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" : boolean
>typeof x : string
>x : string | number | boolean
// change value of x
? (x = 10 && x.toString()) // number | boolean | string
>(x = 10 && x.toString()) : string
>x = 10 && x.toString() : string
>x : string | number | boolean
>10 && x.toString() : string
>x.toString() : string
>x.toString : () => string
>x : string | number | boolean
>toString : () => string
// do not change value
: (y = x && x.toString()))); // number | boolean | string
>(y = x && x.toString()) : string
>y = x && x.toString() : string
>y : string | number | boolean
>x && x.toString() : string
>x : string | number | boolean
>x.toString() : string
>x.toString : () => string
>x : string | number | boolean
>toString : () => string
}
function foo8(x: number | string) {
>foo8 : (x: string | number) => number
>x : string | number
// 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 : string | number
&& (x = 10) // change x - number| string
>(x = 10) : number
>x = 10 : number
>x : string | 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 : string | number
? x // number
>x : number
: x.length); // string
>x.length : number
>x : string
>length : number
}

View File

@@ -0,0 +1,96 @@
//// [typeGuardsInRightOperandOfOrOrOperator.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 false,
// provided the right operand contains no assignments to the variable or parameter.
function foo(x: number | string) {
return typeof x !== "string" || x.length === 10; // string
}
function foo2(x: number | string) {
// modify x in right hand operand
return typeof x !== "string" || ((x = 10) || x); // string | number
}
function foo3(x: number | string) {
// modify x in right hand operand with string type itself
return typeof x !== "string" || ((x = "hello") || x); // string | number
}
function foo4(x: number | string | boolean) {
return typeof x === "string" // string | number | boolean
|| typeof x === "number" // number | boolean
|| x; // boolean
}
function foo5(x: number | string | boolean) {
// usage of x or assignment to separate variable shouldn't cause narrowing of type to stop
var b: number | boolean;
return typeof x === "string" // string | number | boolean
|| ((b = x) || (typeof x === "number" // number | boolean
|| x)); // boolean
}
function foo6(x: number | string | boolean) {
// Mixing typeguard
return typeof x === "string" // string | number | boolean
|| (typeof x !== "number" // number | boolean
? x // boolean
: x === 10) // number
}
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
|| (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 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,
// the type of a variable or parameter is narrowed by any type guard in the left operand when false,
// provided the right operand contains no assignments to the variable or parameter.
function foo(x) {
return typeof x !== "string" || x.length === 10; // string
}
function foo2(x) {
// modify x in right hand operand
return typeof x !== "string" || ((x = 10) || x); // string | number
}
function foo3(x) {
// modify x in right hand operand with string type itself
return typeof x !== "string" || ((x = "hello") || x); // string | number
}
function foo4(x) {
return typeof x === "string" || typeof x === "number" || x; // boolean
}
function foo5(x) {
// usage of x or assignment to separate variable shouldn't cause narrowing of type to stop
var b;
return typeof x === "string" || ((b = x) || (typeof x === "number" || x)); // boolean
}
function foo6(x) {
// Mixing typeguard
return typeof x === "string" || (typeof x !== "number" ? x : x === 10); // number
}
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) || (typeof x === "number" ? (x = 10 && x.toString()) : (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) || (typeof x === "number" ? x : x.length); // string
}

View File

@@ -0,0 +1,215 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfOrOrOperator.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 false,
// provided the right operand contains no assignments to the variable or parameter.
function foo(x: number | string) {
>foo : (x: string | number) => boolean
>x : string | number
return typeof x !== "string" || x.length === 10; // string
>typeof x !== "string" || x.length === 10 : boolean
>typeof x !== "string" : boolean
>typeof x : string
>x : string | number
>x.length === 10 : boolean
>x.length : number
>x : string
>length : number
}
function foo2(x: number | string) {
>foo2 : (x: string | number) => string | number | boolean
>x : string | number
// modify x in right hand operand
return typeof x !== "string" || ((x = 10) || x); // string | number
>typeof x !== "string" || ((x = 10) || x) : string | number | boolean
>typeof x !== "string" : boolean
>typeof x : string
>x : string | number
>((x = 10) || x) : string | number
>(x = 10) || x : string | number
>(x = 10) : number
>x = 10 : number
>x : string | number
>x : string | number
}
function foo3(x: number | string) {
>foo3 : (x: string | number) => string | number | boolean
>x : string | number
// 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) : string | number | boolean
>typeof x !== "string" : boolean
>typeof x : string
>x : string | number
>((x = "hello") || x) : string | number
>(x = "hello") || x : string | number
>(x = "hello") : string
>x = "hello" : string
>x : string | number
>x : string | number
}
function foo4(x: number | string | boolean) {
>foo4 : (x: string | number | boolean) => boolean
>x : string | number | boolean
return typeof x === "string" // string | number | boolean
>typeof x === "string" // string | number | boolean || typeof x === "number" // number | boolean || x : boolean
>typeof x === "string" // string | number | boolean || typeof x === "number" : boolean
>typeof x === "string" : boolean
>typeof x : string
>x : string | number | boolean
|| typeof x === "number" // number | boolean
>typeof x === "number" : boolean
>typeof x : string
>x : number | boolean
|| x; // boolean
>x : boolean
}
function foo5(x: number | string | boolean) {
>foo5 : (x: string | number | boolean) => number | boolean
>x : string | number | boolean
// usage of x or assignment to separate variable shouldn't cause narrowing of type to stop
var b: number | boolean;
>b : number | boolean
return typeof x === "string" // string | number | boolean
>typeof x === "string" // string | number | boolean || ((b = x) || (typeof x === "number" // number | boolean || x)) : number | boolean
>typeof x === "string" : boolean
>typeof x : string
>x : string | number | boolean
|| ((b = x) || (typeof x === "number" // number | boolean
>((b = x) || (typeof x === "number" // number | boolean || x)) : number | boolean
>(b = x) || (typeof x === "number" // number | boolean || x) : number | boolean
>(b = x) : number | boolean
>b = x : number | boolean
>b : number | boolean
>x : number | boolean
>(typeof x === "number" // number | boolean || x) : boolean
>typeof x === "number" // number | boolean || x : boolean
>typeof x === "number" : boolean
>typeof x : string
>x : number | boolean
|| x)); // boolean
>x : boolean
}
function foo6(x: number | string | boolean) {
>foo6 : (x: string | number | boolean) => boolean
>x : string | number | boolean
// Mixing typeguard
return typeof x === "string" // string | number | boolean
>typeof x === "string" // string | number | boolean || (typeof x !== "number" // number | boolean ? x // boolean : x === 10) : boolean
>typeof x === "string" : boolean
>typeof x : string
>x : string | number | boolean
|| (typeof x !== "number" // number | boolean
>(typeof x !== "number" // number | boolean ? x // boolean : x === 10) : boolean
>typeof x !== "number" // number | boolean ? x // boolean : x === 10 : boolean
>typeof x !== "number" : boolean
>typeof x : string
>x : number | boolean
? x // boolean
>x : boolean
: x === 10) // number
>x === 10 : boolean
>x : number
}
function foo7(x: number | string | boolean) {
>foo7 : (x: string | number | boolean) => string | number | boolean
>x : string | number | boolean
var y: number| boolean | string;
>y : string | number | boolean
var z: number| boolean | string;
>z : string | number | boolean
// 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 | number | boolean
>typeof x === "string" : boolean
>typeof x : string
>x : string | number | boolean
|| ((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 | number | 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())) : string | number | boolean
>(z = x) : string | number | boolean
>z = x : string | number | boolean
>z : string | number | boolean
>x : string | 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" : boolean
>typeof x : string
>x : string | number | boolean
// change value of x
? (x = 10 && x.toString()) // number | boolean | string
>(x = 10 && x.toString()) : string
>x = 10 && x.toString() : string
>x : string | number | boolean
>10 && x.toString() : string
>x.toString() : string
>x.toString : () => string
>x : string | number | boolean
>toString : () => string
// do not change value
: (y = x && x.toString()))); // number | boolean | string
>(y = x && x.toString()) : string
>y = x && x.toString() : string
>y : string | number | boolean
>x && x.toString() : string
>x : string | number | boolean
>x.toString() : string
>x.toString : () => string
>x : string | number | boolean
>toString : () => string
}
function foo8(x: number | string) {
>foo8 : (x: string | number) => number | boolean
>x : string | number
// 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 | boolean
>typeof x === "string" || (x = 10) : number | boolean
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
|| (x = 10) // change x - number| string
>(x = 10) : number
>x = 10 : number
>x : string | 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 : string | number
? x // number
>x : number
: x.length); // string
>x.length : number
>x : string
>length : number
}

View File

@@ -0,0 +1,93 @@
//// [typeGuardsObjectMethods.ts]
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num: number;
var strOrNum: string | number;
var var1: string | number;
var obj1 = {
// Inside method
method(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
return strOrNum;
},
get prop() {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
return strOrNum;
},
set prop(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
}
};
// return expression of the method
strOrNum = typeof obj1.method(strOrNum) === "string" && obj1.method(strOrNum);
// accessing getter property
strOrNum = typeof obj1.prop === "string" && obj1.prop;
//// [typeGuardsObjectMethods.js]
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num;
var strOrNum;
var var1;
var obj1 = {
// Inside method
method: function (param) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
return strOrNum;
},
get prop() {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2;
num = typeof var2 === "string" && var2.length; // string
return strOrNum;
},
set prop(param) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
}
};
// return expression of the method
strOrNum = typeof obj1.method(strOrNum) === "string" && obj1.method(strOrNum);
// accessing getter property
strOrNum = typeof obj1.prop === "string" && obj1.prop;

View File

@@ -0,0 +1,178 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsObjectMethods.ts ===
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num: number;
>num : number
var strOrNum: string | number;
>strOrNum : string | number
var var1: string | number;
>var1 : string | number
var obj1 = {
>obj1 : { method: (param: string | number) => string | number; prop: string | number; }
>{ // Inside method method(param: string | number) { // global vars in function declaration num = typeof var1 === "string" && var1.length; // string // variables in function declaration var var2: string | number; num = typeof var2 === "string" && var2.length; // string // parameters in function declaration num = typeof param === "string" && param.length; // string return strOrNum; }, get prop() { // global vars in function declaration num = typeof var1 === "string" && var1.length; // string // variables in function declaration var var2: string | number; num = typeof var2 === "string" && var2.length; // string return strOrNum; }, set prop(param: string | number) { // global vars in function declaration num = typeof var1 === "string" && var1.length; // string // variables in function declaration var var2: string | number; num = typeof var2 === "string" && var2.length; // string // parameters in function declaration num = typeof param === "string" && param.length; // string }} : { method: (param: string | number) => string | number; prop: string | number; }
// Inside method
method(param: string | number) {
>method : (param: string | number) => string | number
>method(param: string | number) { // global vars in function declaration num = typeof var1 === "string" && var1.length; // string // variables in function declaration var var2: string | number; num = typeof var2 === "string" && var2.length; // string // parameters in function declaration num = typeof param === "string" && param.length; // string return strOrNum; } : (param: string | number) => string | number
>param : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// variables in function declaration
var var2: string | number;
>var2 : string | number
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
// parameters in function declaration
num = typeof param === "string" && param.length; // string
>num = typeof param === "string" && param.length : number
>num : number
>typeof param === "string" && param.length : number
>typeof param === "string" : boolean
>typeof param : string
>param : string | number
>param.length : number
>param : string
>length : number
return strOrNum;
>strOrNum : string | number
},
get prop() {
>prop : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// variables in function declaration
var var2: string | number;
>var2 : string | number
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
return strOrNum;
>strOrNum : string | number
},
set prop(param: string | number) {
>prop : string | number
>param : string | number
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
>num = typeof var1 === "string" && var1.length : number
>num : number
>typeof var1 === "string" && var1.length : number
>typeof var1 === "string" : boolean
>typeof var1 : string
>var1 : string | number
>var1.length : number
>var1 : string
>length : number
// variables in function declaration
var var2: string | number;
>var2 : string | number
num = typeof var2 === "string" && var2.length; // string
>num = typeof var2 === "string" && var2.length : number
>num : number
>typeof var2 === "string" && var2.length : number
>typeof var2 === "string" : boolean
>typeof var2 : string
>var2 : string | number
>var2.length : number
>var2 : string
>length : number
// parameters in function declaration
num = typeof param === "string" && param.length; // string
>num = typeof param === "string" && param.length : number
>num : number
>typeof param === "string" && param.length : number
>typeof param === "string" : boolean
>typeof param : string
>param : string | number
>param.length : number
>param : string
>length : number
}
};
// return expression of the method
strOrNum = typeof obj1.method(strOrNum) === "string" && obj1.method(strOrNum);
>strOrNum = typeof obj1.method(strOrNum) === "string" && obj1.method(strOrNum) : string | number
>strOrNum : string | number
>typeof obj1.method(strOrNum) === "string" && obj1.method(strOrNum) : string | number
>typeof obj1.method(strOrNum) === "string" : boolean
>typeof obj1.method(strOrNum) : string
>obj1.method(strOrNum) : string | number
>obj1.method : (param: string | number) => string | number
>obj1 : { method: (param: string | number) => string | number; prop: string | number; }
>method : (param: string | number) => string | number
>strOrNum : string | number
>obj1.method(strOrNum) : string | number
>obj1.method : (param: string | number) => string | number
>obj1 : { method: (param: string | number) => string | number; prop: string | number; }
>method : (param: string | number) => string | number
>strOrNum : string | number
// accessing getter property
strOrNum = typeof obj1.prop === "string" && obj1.prop;
>strOrNum = typeof obj1.prop === "string" && obj1.prop : string | number
>strOrNum : string | number
>typeof obj1.prop === "string" && obj1.prop : string | number
>typeof obj1.prop === "string" : boolean
>typeof obj1.prop : string
>obj1.prop : string | number
>obj1 : { method: (param: string | number) => string | number; prop: string | number; }
>prop : string | number
>obj1.prop : string | number
>obj1 : { method: (param: string | number) => string | number; prop: string | number; }
>prop : string | number

View File

@@ -0,0 +1,46 @@
var str: string;
var bool: boolean;
var num: number;
var strOrNum: string | number;
var strOrNumOrBool: string | number | boolean;
var numOrBool: number | boolean;
class C { private p; }
var c: C;
var cOrBool: C| boolean;
var strOrNumOrBoolOrC: string | number | boolean | C;
// A type guard of the form expr1 && expr2
// - when true, narrows the type of x by expr1 when true and then by expr2 when true, or
// - when false, narrows the type of x to T1 | T2, where T1 is the type of x narrowed by expr1 when
// false, and T2 is the type of x narrowed by expr1 when true and then by expr2 when false.
// (typeguard1 && typeguard2)
if (typeof strOrNumOrBool !== "string" && typeof strOrNumOrBool !== "number") {
bool = strOrNumOrBool; // boolean
}
else {
strOrNum = strOrNumOrBool; // string | number
}
// (typeguard1 && typeguard2 && typeguard3)
if (typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "number" && typeof strOrNumOrBoolOrC !== "boolean") {
c = strOrNumOrBoolOrC; // C
}
else {
strOrNumOrBool = strOrNumOrBoolOrC; // string | number | boolean
}
// (typeguard1 && typeguard2 && typeguard11(onAnotherType))
if (typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "number" && typeof strOrNumOrBool === "boolean") {
cOrBool = strOrNumOrBoolOrC; // C | boolean
bool = strOrNumOrBool; // boolean
}
else {
var r1: string | number | boolean | C = strOrNumOrBoolOrC; // string | number | boolean | C
var r2: string | number | boolean = strOrNumOrBool;
}
// (typeguard1) && simpleExpr
if (typeof strOrNumOrBool !== "string" && numOrBool !== strOrNumOrBool) {
numOrBool = strOrNumOrBool; // number | boolean
}
else {
var r3: string | number | boolean = strOrNumOrBool; // string | number | boolean
}

View File

@@ -0,0 +1,46 @@
var str: string;
var bool: boolean;
var num: number;
var strOrNum: string | number;
var strOrNumOrBool: string | number | boolean;
var numOrBool: number | boolean;
class C { private p; }
var c: C;
var cOrBool: C| boolean;
var strOrNumOrBoolOrC: string | number | boolean | C;
// A type guard of the form expr1 || expr2
// - when true, narrows the type of x to T1 | T2, where T1 is the type of x narrowed by expr1 when true,
// and T2 is the type of x narrowed by expr1 when false and then by expr2 when true, or
// - when false, narrows the type of x by expr1 when false and then by expr2 when false.
// (typeguard1 || typeguard2)
if (typeof strOrNumOrBool === "string" || typeof strOrNumOrBool === "number") {
strOrNum = strOrNumOrBool; // string | number
}
else {
bool = strOrNumOrBool; // boolean
}
// (typeguard1 || typeguard2 || typeguard3)
if (typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "number" || typeof strOrNumOrBoolOrC === "boolean") {
strOrNumOrBool = strOrNumOrBoolOrC; // string | number | boolean
}
else {
c = strOrNumOrBoolOrC; // C
}
// (typeguard1 || typeguard2 || typeguard11(onAnotherType))
if (typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "number" || typeof strOrNumOrBool !== "boolean") {
var r1: string | number | boolean | C = strOrNumOrBoolOrC; // string | number | boolean | C
var r2: string | number | boolean = strOrNumOrBool;
}
else {
cOrBool = strOrNumOrBoolOrC; // C | boolean
bool = strOrNumOrBool; // boolean
}
// (typeguard1) || simpleExpr
if (typeof strOrNumOrBool === "string" || numOrBool !== strOrNumOrBool) {
var r3: string | number | boolean = strOrNumOrBool; // string | number | boolean
}
else {
numOrBool = strOrNumOrBool; // number | boolean
}

View File

@@ -0,0 +1,30 @@
// A type guard of the form x instanceof C, where C is of a subtype of the global type 'Function'
// and C has a property named 'prototype'
// - when true, narrows the type of x to the type of the 'prototype' property in C provided
// it is a subtype of the type of x, or
// - when false, has no effect on the type of x.
class C1 {
p1: string;
}
class C2 {
p2: number;
}
class D1 extends C1 {
p3: number;
}
var str: string;
var num: number;
var strOrNum: string | number;
var c1Orc2: C1 | C2;
str = c1Orc2 instanceof C1 && c1Orc2.p1; // C1
num = c1Orc2 instanceof C2 && c1Orc2.p2; // C2
str = c1Orc2 instanceof D1 && c1Orc2.p1; // D1
num = c1Orc2 instanceof D1 && c1Orc2.p3; // D1
var c2Ord1: C2 | D1;
num = c2Ord1 instanceof C2 && c2Ord1.p2; // C2
num = c2Ord1 instanceof D1 && c2Ord1.p3; // D1
str = c2Ord1 instanceof D1 && c2Ord1.p1; // D1
var r2: D1 | C2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1

View File

@@ -0,0 +1,38 @@
// A type guard of the form x instanceof C, where C is of a subtype of the global type 'Function'
// and C has a property named 'prototype'
// - when true, narrows the type of x to the type of the 'prototype' property in C provided
// it is a subtype of the type of x, or
// - when false, has no effect on the type of x.
interface C1 {
(): C1;
prototype: C1;
p1: string;
}
interface C2 {
(): C2;
prototype: C2;
p2: number;
}
interface D1 extends C1 {
prototype: D1;
p3: number;
}
var str: string;
var num: number;
var strOrNum: string | number;
var c1: C1;
var c2: C2;
var d1: D1;
var c1Orc2: C1 | C2;
str = c1Orc2 instanceof c1 && c1Orc2.p1; // C1
num = c1Orc2 instanceof c2 && c1Orc2.p2; // C2
str = c1Orc2 instanceof d1 && c1Orc2.p1; // C1
num = c1Orc2 instanceof d1 && c1Orc2.p3; // D1
var c2Ord1: C2 | D1;
num = c2Ord1 instanceof c2 && c2Ord1.p2; // C2
num = c2Ord1 instanceof d1 && c2Ord1.p3; // D1
str = c2Ord1 instanceof d1 && c2Ord1.p1; // D1
var r2: D1 | C2 = c2Ord1 instanceof c1 && c2Ord1; // C2 | D1

View File

@@ -0,0 +1,53 @@
var str: string;
var bool: boolean;
var num: number;
var strOrNum: string | number;
var strOrNumOrBool: string | number | boolean;
var numOrBool: number | boolean;
// A type guard of the form !expr
// - when true, narrows the type of x by expr when false, or
// - when false, narrows the type of x by expr when true.
// !typeguard1
if (!(typeof strOrNum === "string")) {
num === strOrNum; // number
}
else {
str = strOrNum; // string
}
// !(typeguard1 || typeguard2)
if (!(typeof strOrNumOrBool === "string" || typeof strOrNumOrBool === "number")) {
bool = strOrNumOrBool; // boolean
}
else {
strOrNum = strOrNumOrBool; // string | number
}
// !(typeguard1) || !(typeguard2)
if (!(typeof strOrNumOrBool !== "string") || !(typeof strOrNumOrBool !== "number")) {
strOrNum = strOrNumOrBool; // string | number
}
else {
bool = strOrNumOrBool; // boolean
}
// !(typeguard1 && typeguard2)
if (!(typeof strOrNumOrBool !== "string" && typeof strOrNumOrBool !== "number")) {
strOrNum = strOrNumOrBool; // string | number
}
else {
bool = strOrNumOrBool; // boolean
}
// !(typeguard1) && !(typeguard2)
if (!(typeof strOrNumOrBool === "string") && !(typeof strOrNumOrBool === "number")) {
bool = strOrNumOrBool; // boolean
}
else {
strOrNum = strOrNumOrBool; // string | number
}
// !(typeguard1) && simpleExpr
if (!(typeof strOrNumOrBool === "string") && numOrBool !== strOrNumOrBool) {
numOrBool = strOrNumOrBool; // number | boolean
}
else {
var r1: string | number | boolean = strOrNumOrBool; // string | number | boolean
}

View File

@@ -0,0 +1,82 @@
class C { private p: string };
var str: string;
var bool: boolean;
var num: number;
var strOrNum: string | number;
var strOrBool: string | boolean;
var numOrBool: number | boolean
var strOrNumOrBool: string | number | boolean;
var strOrC: string | C;
var numOrC: number | C;
var boolOrC: boolean | C;
var c: C;
// A type guard of the form typeof x === s,
// where s is a string literal with the value 'string', 'number', or 'boolean',
// - when true, narrows the type of x to the given primitive type, or
// - when false, removes the primitive type from the type of x.
if (typeof strOrNum === "boolean") {
bool = strOrNum; // boolean
}
else {
var z: string | number = strOrNum; // string | number
}
if (typeof strOrBool === "boolean") {
bool = strOrBool; // boolean
}
else {
str = strOrBool; // string
}
if (typeof numOrBool === "boolean") {
bool = numOrBool; // boolean
}
else {
num = numOrBool; // number
}
if (typeof strOrNumOrBool === "boolean") {
bool = strOrNumOrBool; // boolean
}
else {
strOrNum = strOrNumOrBool; // string | number
}
if (typeof boolOrC === "boolean") {
bool = boolOrC; // boolean
}
else {
c = boolOrC; // C
}
// A type guard of the form typeof x !== s, where s is a string literal,
// - when true, narrows the type of x by typeof x === s when false, or
// - when false, narrows the type of x by typeof x === s when true.
if (typeof strOrNum !== "boolean") {
var z: string | number = strOrNum; // string | number
}
else {
bool = strOrNum; // boolean
}
if (typeof strOrBool !== "boolean") {
str = strOrBool; // string
}
else {
bool = strOrBool; // boolean
}
if (typeof numOrBool !== "boolean") {
num = numOrBool; // number
}
else {
bool = numOrBool; // boolean
}
if (typeof strOrNumOrBool !== "boolean") {
strOrNum = strOrNumOrBool; // string | number
}
else {
bool = strOrNumOrBool; // boolean
}
if (typeof boolOrC !== "boolean") {
c = boolOrC; // C
}
else {
bool = boolOrC; // boolean
}

View File

@@ -0,0 +1,35 @@
class C { private p: string };
var strOrNum: string | number;
var strOrBool: string | boolean;
var numOrBool: number | boolean
var strOrC: string | C;
// typeof x == s has not effect on typeguard
if (typeof strOrNum == "string") {
var r1 = strOrNum; // string | number
}
else {
var r1 = strOrNum; // string | number
}
if (typeof strOrBool == "boolean") {
var r2 = strOrBool; // string | boolean
}
else {
var r2 = strOrBool; // string | boolean
}
if (typeof numOrBool == "number") {
var r3 = numOrBool; // number | boolean
}
else {
var r3 = numOrBool; // number | boolean
}
if (typeof strOrC == "Object") {
var r4 = strOrC; // string | C
}
else {
var r4 = strOrC; // string | C
}

View File

@@ -0,0 +1,35 @@
class C { private p: string };
var strOrNum: string | number;
var strOrBool: string | boolean;
var numOrBool: number | boolean
var strOrC: string | C;
// typeof x != s has not effect on typeguard
if (typeof strOrNum != "string") {
var r1 = strOrNum; // string | number
}
else {
var r1 = strOrNum; // string | number
}
if (typeof strOrBool != "boolean") {
var r2 = strOrBool; // string | boolean
}
else {
var r2 = strOrBool; // string | boolean
}
if (typeof numOrBool != "number") {
var r3 = numOrBool; // number | boolean
}
else {
var r3 = numOrBool; // number | boolean
}
if (typeof strOrC != "Object") {
var r4 = strOrC; // string | C
}
else {
var r4 = strOrC; // string | C
}

View File

@@ -0,0 +1,82 @@
class C { private p: string };
var str: string;
var bool: boolean;
var num: number;
var strOrNum: string | number;
var strOrBool: string | boolean;
var numOrBool: number | boolean
var strOrNumOrBool: string | number | boolean;
var strOrC: string | C;
var numOrC: number | C;
var boolOrC: boolean | C;
var c: C;
// A type guard of the form typeof x === s,
// where s is a string literal with the value 'string', 'number', or 'boolean',
// - when true, narrows the type of x to the given primitive type, or
// - when false, removes the primitive type from the type of x.
if (typeof strOrNum === "number") {
num = strOrNum; // number
}
else {
str === strOrNum; // string
}
if (typeof strOrBool === "number") {
num = strOrBool; // number
}
else {
var y: string | boolean = strOrBool; // string | boolean
}
if (typeof numOrBool === "number") {
num = numOrBool; // number
}
else {
var x: number | boolean = numOrBool; // number | boolean
}
if (typeof strOrNumOrBool === "number") {
num = strOrNumOrBool; // number
}
else {
strOrBool = strOrNumOrBool; // string | boolean
}
if (typeof numOrC === "number") {
num = numOrC; // number
}
else {
c = numOrC; // C
}
// A type guard of the form typeof x !== s, where s is a string literal,
// - when true, narrows the type of x by typeof x === s when false, or
// - when false, narrows the type of x by typeof x === s when true.
if (typeof strOrNum !== "number") {
str === strOrNum; // string
}
else {
num = strOrNum; // number
}
if (typeof strOrBool !== "number") {
var y: string | boolean = strOrBool; // string | boolean
}
else {
num = strOrBool; // number
}
if (typeof numOrBool !== "number") {
var x: number | boolean = numOrBool; // number | boolean
}
else {
num = numOrBool; // number
}
if (typeof strOrNumOrBool !== "number") {
strOrBool = strOrNumOrBool; // string | boolean
}
else {
num = strOrNumOrBool; // number
}
if (typeof numOrC !== "number") {
c = numOrC; // C
}
else {
num = numOrC; // number
}

View File

@@ -0,0 +1,72 @@
class C { private p: string };
var str: string;
var bool: boolean;
var num: number;
var strOrNum: string | number;
var strOrBool: string | boolean;
var numOrBool: number | boolean
var strOrNumOrBool: string | number | boolean;
var strOrC: string | C;
var numOrC: number | C;
var boolOrC: boolean | C;
var emptyObj: {};
var c: C;
// A type guard of the form typeof x === s,
// where s is a string literal with any value but 'string', 'number' or 'boolean',
// - when true, removes the primitive types string, number, and boolean from the type of x, or
// - when false, has no effect on the type of x.
if (typeof strOrNumOrBool === "Object") {
emptyObj = strOrNumOrBool; // {}
}
else {
var r1: string | number | boolean = strOrNumOrBool; // string | number | boolean
}
if (typeof strOrC === "Object") {
c = strOrC; // C
}
else {
var r2: string | C = strOrC; // string | C
}
if (typeof numOrC === "Object") {
c = numOrC; // C
}
else {
var r3: number | C = numOrC; // number | C
}
if (typeof boolOrC === "Object") {
c = boolOrC; // C
}
else {
var r4: boolean | C = boolOrC; // boolean | C
}
// A type guard of the form typeof x !== s, where s is a string literal,
// - when true, narrows the type of x by typeof x === s when false, or
// - when false, narrows the type of x by typeof x === s when true.
if (typeof strOrNumOrBool !== "Object") {
var r1: string | number | boolean = strOrNumOrBool; // string | number | boolean
}
else {
emptyObj = strOrNumOrBool; // {}
}
if (typeof strOrC !== "Object") {
var r2: string | C = strOrC; // string | C
}
else {
c = strOrC; // C
}
if (typeof numOrC !== "Object") {
var r3: number | C = numOrC; // number | C
}
else {
c = numOrC; // C
}
if (typeof boolOrC !== "Object") {
var r4: boolean | C = boolOrC; // boolean | C
}
else {
c = boolOrC; // C
}

View File

@@ -0,0 +1,82 @@
class C { private p: string };
var str: string;
var bool: boolean;
var num: number;
var strOrNum: string | number;
var strOrBool: string | boolean;
var numOrBool: number | boolean
var strOrNumOrBool: string | number | boolean;
var strOrC: string | C;
var numOrC: number | C;
var boolOrC: boolean | C;
var c: C;
// A type guard of the form typeof x === s,
// where s is a string literal with the value 'string', 'number', or 'boolean',
// - when true, narrows the type of x to the given primitive type, or
// - when false, removes the primitive type from the type of x.
if (typeof strOrNum === "string") {
str = strOrNum; // string
}
else {
num === strOrNum; // number
}
if (typeof strOrBool === "string") {
str = strOrBool; // string
}
else {
bool = strOrBool; // boolean
}
if (typeof numOrBool === "string") {
str = numOrBool; // string
}
else {
var x : number | boolean = numOrBool; // number | boolean
}
if (typeof strOrNumOrBool === "string") {
str = strOrNumOrBool; // string
}
else {
numOrBool = strOrNumOrBool; // number | boolean
}
if (typeof strOrC === "string") {
str = strOrC; // string
}
else {
c = strOrC; // C
}
// A type guard of the form typeof x !== s, where s is a string literal,
// - when true, narrows the type of x by typeof x === s when false, or
// - when false, narrows the type of x by typeof x === s when true.
if (typeof strOrNum !== "string") {
num === strOrNum; // number
}
else {
str = strOrNum; // string
}
if (typeof strOrBool !== "string") {
bool = strOrBool; // boolean
}
else {
str = strOrBool; // string
}
if (typeof numOrBool !== "string") {
var x: number | boolean = numOrBool; // number | boolean
}
else {
str = numOrBool; // string
}
if (typeof strOrNumOrBool !== "string") {
numOrBool = strOrNumOrBool; // number | boolean
}
else {
str = strOrNumOrBool; // string
}
if (typeof strOrC !== "string") {
c = strOrC; // C
}
else {
str = strOrC; // string
}

View File

@@ -0,0 +1,36 @@
// Also note that it is possible to defeat a type guard by calling a function that changes the
// type of the guarded variable.
function foo(x: number | string) {
function f() {
x = 10;
}
if (typeof x === "string") {
f();
return x.length; // string
}
else {
return x++; // number
}
}
function foo2(x: number | string) {
if (typeof x === "string") {
return x.length; // string
}
else {
(function f() {
x = 10;
})();
return x++; // number
}
}
function foo3(x: number | string) {
if (typeof x === "string") {
return x.length; // string
}
else {
(() => {
x = 10;
})();
return x++; // number
}
}

View File

@@ -0,0 +1,103 @@
//@target: es5
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num: number;
var strOrNum: string | number;
var var1: string | number;
class ClassWithAccessors {
// Inside public accessor getter
get p1() {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
return strOrNum;
}
// Inside public accessor setter
set p1(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// parameter of function declaration
num = typeof param === "string" && param.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
}
// Inside private accessor getter
private get pp1() {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
return strOrNum;
}
// Inside private accessor setter
private set pp1(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// parameter of function declaration
num = typeof param === "string" && param.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
}
// Inside static accessor getter
static get s1() {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
return strOrNum;
}
// Inside static accessor setter
static set s1(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// parameter of function declaration
num = typeof param === "string" && param.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
}
// Inside private static accessor getter
private static get ss1() {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
return strOrNum;
}
// Inside private static accessor setter
private static set ss1(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// parameter of function declaration
num = typeof param === "string" && param.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
}
}

View File

@@ -0,0 +1,67 @@
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num: number;
var var1: string | number;
class C1 {
constructor(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
}
// Inside function declaration
private p1(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
}
// Inside function declaration
p2(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
}
// Inside function declaration
private static s1(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
}
// Inside function declaration
static s2(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
}
}

View File

@@ -0,0 +1,97 @@
// In the true expression of a conditional expression,
// the type of a variable or parameter is narrowed by any type guard in the condition when true,
// provided the true expression contains no assignments to the variable or parameter.
// In the false expression of a conditional expression,
// the type of a variable or parameter is narrowed by any type guard in the condition when false,
// provided the false expression contains no assignments to the variable or parameter.
function foo(x: number | string) {
return typeof x === "string"
? x.length // 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
}
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
}
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
}
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
}
function foo6(x: number | string) {
// Modify in both branches
return typeof x === "string"
? (x = 10 && x) // string | number
: (x = "hello" && x); // string | number
}
function foo7(x: number | string | boolean) {
return typeof x === "string"
? x === "hello" // string
: typeof x === "boolean"
? x // boolean
: x == 10; // number
}
function foo8(x: number | string | boolean) {
var b: number | boolean;
return typeof x === "string"
? x === "hello"
: ((b = x) && // number | boolean
(typeof x === "boolean"
? x // boolean
: x == 10)); // number
}
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
}
function foo10(x: number | string | boolean) {
// Mixing typeguards
var b: boolean | number;
return typeof x === "string"
? x // string
: ((b = x) // x is number | boolean
&& typeof x === "number"
&& x.toString()); // x is number
}
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
&& typeof x === "number"
&& (x = 10) // assignment to x
&& x); // x is number | boolean | string
}
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
&& typeof x === "number"
&& x); // x is number
}

View File

@@ -0,0 +1,24 @@
//@module: commonjs
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// local variable in external module
var num: number;
var var1: string | number;
if (typeof var1 === "string") {
num = var1.length; // string
}
else {
num = var1; // number
}
// exported variable in external module
var strOrNum: string | number;
export var var2: string | number;
if (typeof var2 === "string") {
// export makes the var property and not variable
strOrNum = var2; // string | number
}
else {
strOrNum = var2; // number | string
}

View File

@@ -0,0 +1,87 @@
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num: number;
var var1: string | number;
// Inside function declaration
function f(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
}
// local function declaration
function f1(param: string | number) {
var var2: string | number;
function f2(param1: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables from outer function declaration
num = typeof var2 === "string" && var2.length; // string
// parameters in outer declaration
num = typeof param === "string" && param.length; // string
// local
var var3: string | number;
num = typeof var3 === "string" && var3.length; // string
num = typeof param1 === "string" && param1.length; // string
}
}
// Function expression
function f2(param: string | number) {
// variables in function declaration
var var2: string | number;
// variables in function expressions
var r = function (param1: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables from outer function declaration
num = typeof var2 === "string" && var2.length; // string
// parameters in outer declaration
num = typeof param === "string" && param.length; // string
// local
var var3: string | number;
num = typeof var3 === "string" && var3.length; // string
num = typeof param1 === "string" && param1.length; // string
} (param);
}
// Arrow expression
function f3(param: string | number) {
// variables in function declaration
var var2: string | number;
// variables in function expressions
var r = ((param1: string | number) => {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables from outer function declaration
num = typeof var2 === "string" && var2.length; // string
// parameters in outer declaration
num = typeof param === "string" && param.length; // string
// local
var var3: string | number;
num = typeof var3 === "string" && var3.length; // string
num = typeof param1 === "string" && param1.length; // string
})(param);
}
// Return type of function
// Inside function declaration
var strOrNum: string | number;
function f4() {
var var2: string | number = strOrNum;
return var2;
}
strOrNum = typeof f4() === "string" && f4(); // string | number

View File

@@ -0,0 +1,70 @@
// typeguards are scoped in function/module block
function foo(x: number | string | boolean) {
return typeof x === "string"
? x
: function f() {
var b = x; // new scope - number | boolean | string
return typeof x === "boolean"
? x.toString() // boolean
: x.toString(); // number | string
} ();
}
function foo2(x: number | string | boolean) {
return typeof x === "string"
? x
: function f(a: number | boolean) {
var b = x; // new scope - number | boolean | string
return typeof x === "boolean"
? x.toString() // boolean
: x.toString(); // number | string
} (x); // x here is narrowed to number | boolean
}
function foo3(x: number | string | boolean) {
return typeof x === "string"
? x
: (() => {
var b = x; // new scope - number | boolean | string
return typeof x === "boolean"
? x.toString() // boolean
: x.toString(); // number | string
})();
}
function foo4(x: number | string | boolean) {
return typeof x === "string"
? x
: ((a: number | boolean) => {
var b = x; // new scope - number | boolean | string
return typeof x === "boolean"
? x.toString() // boolean
: x.toString(); // number | string
})(x); // x here is narrowed to number | boolean
}
module m {
var x: number | string | boolean;
module m2 {
var b = x; // new scope - number | boolean | string
var y: string;
if (typeof x === "string") {
y = x // string;
} else {
y = typeof x === "boolean"
? x.toString() // boolean
: x.toString(); // number
}
}
}
module m1 {
var x: number | string | boolean;
module m2.m3 {
var b = x; // new scope - number | boolean | string
var y: string;
if (typeof x === "string") {
y = x // string;
} else {
y = typeof x === "boolean"
? x.toString() // boolean
: x.toString(); // number
}
}
}

View File

@@ -0,0 +1,12 @@
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num: number;
var var1: string | number;
if (typeof var1 === "string") {
num = var1.length; // string
}
else {
num = var1; // number
}

View File

@@ -0,0 +1,148 @@
// 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) {
if (typeof x === "string") {
return x.length; // string
}
else {
return x++; // number
}
}
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
}
else {
return x; // string | 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
}
else {
return x; // string | 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
}
else {
x = 10; // even though assigned number - this should result in x to be string | number
return x; // string | 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
}
else {
x = "hello";
return x; // string | number
}
}
function foo6(x: number | string) {
// Modify in both branches
if (typeof x === "string") {
x = 10;
return x; // string | number
}
else {
x = "hello";
return x; // string | number
}
}
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
}
}

View File

@@ -0,0 +1,86 @@
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num: number;
var strOrNum: string | number;
var var1: string | number;
// Inside module
module m1 {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in module declaration
var var2: string | number;
if (typeof var2 === "string") {
num = var2.length; // string
}
else {
num = var2; // number
}
// exported variable in the module
export var var3: string | number;
if (typeof var3 === "string") {
strOrNum = var3; // string | number
}
else {
strOrNum = var3; // string | number
}
}
// local module
module m2 {
var var2: string | number;
export var var3: string | number;
module m3 {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// local variables from outer module declaration
num = typeof var2 === "string" && var2.length; // string
// exported variable from outer the module
strOrNum = typeof var3 === "string" && var3; // string | number
// variables in module declaration
var var4: string | number;
if (typeof var4 === "string") {
num = var4.length; // string
}
else {
num = var4; // number
}
// exported variable in the module
export var var5: string | number;
if (typeof var5 === "string") {
strOrNum = var5; // string | number
}
else {
strOrNum = var5; // string | number
}
}
}
// Dotted module
module m3.m4 {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in module declaration
var var2: string | number;
if (typeof var2 === "string") {
num = var2.length; // string
}
else {
num = var2; // number
}
// exported variable in the module
export var var3: string | number;
if (typeof var3 === "string") {
strOrNum = var3; // string | number
}
else {
strOrNum = var3; // string | number
}
}

View File

@@ -0,0 +1,27 @@
//@target: es5
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
var num: number;
var strOrNum: string | number;
class C1 {
private pp1: string | number;
pp2: string | number;
// Inside public accessor getter
get pp3() {
return strOrNum;
}
method() {
strOrNum = typeof this.pp1 === "string" && this.pp1; // string | number
strOrNum = typeof this.pp2 === "string" && this.pp2; // string | number
strOrNum = typeof this.pp3 === "string" && this.pp3; // string | number
}
}
var c1: C1;
strOrNum = typeof c1.pp2 === "string" && c1.pp2; // string | number
strOrNum = typeof c1.pp3 === "string" && c1.pp3; // string | number
var obj1: {
x: string | number;
};
strOrNum = typeof obj1.x === "string" && obj1.x; // string | number

View File

@@ -0,0 +1,55 @@
// 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.
function foo(x: number | string) {
return typeof x === "string" && x.length === 10; // string
}
function foo2(x: number | string) {
// modify x in right hand operand
return typeof x === "string" && ((x = 10) && x); // string | number
}
function foo3(x: number | string) {
// modify x in right hand operand with string type itself
return typeof x === "string" && ((x = "hello") && x); // string | number
}
function foo4(x: number | string | boolean) {
return typeof x !== "string" // string | number | boolean
&& typeof x !== "number" // number | boolean
&& x; // boolean
}
function foo5(x: number | string | boolean) {
// usage of x or assignment to separate variable shouldn't cause narrowing of type to stop
var b: number | boolean;
return typeof x !== "string" // string | number | boolean
&& ((b = x) && (typeof x !== "number" // number | boolean
&& x)); // boolean
}
function foo6(x: number | string | boolean) {
// Mixing typeguard narrowing in if statement with conditional expression typeguard
return typeof x !== "string" // string | number | boolean
&& (typeof x !== "number" // number | boolean
? x // boolean
: x === 10) // number
}
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
&& (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 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
}

View File

@@ -0,0 +1,55 @@
// 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 false,
// provided the right operand contains no assignments to the variable or parameter.
function foo(x: number | string) {
return typeof x !== "string" || x.length === 10; // string
}
function foo2(x: number | string) {
// modify x in right hand operand
return typeof x !== "string" || ((x = 10) || x); // string | number
}
function foo3(x: number | string) {
// modify x in right hand operand with string type itself
return typeof x !== "string" || ((x = "hello") || x); // string | number
}
function foo4(x: number | string | boolean) {
return typeof x === "string" // string | number | boolean
|| typeof x === "number" // number | boolean
|| x; // boolean
}
function foo5(x: number | string | boolean) {
// usage of x or assignment to separate variable shouldn't cause narrowing of type to stop
var b: number | boolean;
return typeof x === "string" // string | number | boolean
|| ((b = x) || (typeof x === "number" // number | boolean
|| x)); // boolean
}
function foo6(x: number | string | boolean) {
// Mixing typeguard
return typeof x === "string" // string | number | boolean
|| (typeof x !== "number" // number | boolean
? x // boolean
: x === 10) // number
}
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
|| (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 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
}

View File

@@ -0,0 +1,51 @@
//@target: es5
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// variables in global
var num: number;
var strOrNum: string | number;
var var1: string | number;
var obj1 = {
// Inside method
method(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
return strOrNum;
},
get prop() {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
return strOrNum;
},
set prop(param: string | number) {
// global vars in function declaration
num = typeof var1 === "string" && var1.length; // string
// variables in function declaration
var var2: string | number;
num = typeof var2 === "string" && var2.length; // string
// parameters in function declaration
num = typeof param === "string" && param.length; // string
}
};
// return expression of the method
strOrNum = typeof obj1.method(strOrNum) === "string" && obj1.method(strOrNum);
// accessing getter property
strOrNum = typeof obj1.prop === "string" && obj1.prop;