From cf52ce63a4aed7d3ee609b51ed9be7adb8a9c7a9 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 27 Oct 2015 16:28:56 -0700 Subject: [PATCH 1/2] new test --- .../expressions/typeGuards/typeGuardDuplicateGuards.ts | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 tests/cases/conformance/expressions/typeGuards/typeGuardDuplicateGuards.ts diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardDuplicateGuards.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardDuplicateGuards.ts new file mode 100644 index 0000000000000..4e9e3137d7871 --- /dev/null +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardDuplicateGuards.ts @@ -0,0 +1,9 @@ +var x: string|number; + +var r1 = typeof x === "string" && typeof x === "string" ? x.substr : x.toFixed; + +var r2 = !(typeof x === "string" && typeof x === "string") ? x.toFixed : x.substr; + +var r3 = typeof x === "string" || typeof x === "string" ? x.substr : x.toFixed; + +var r4 = !(typeof x === "string" || typeof x === "string") ? x.toFixed : x.substr; \ No newline at end of file From 41e84e11d23e57a8194f8b3cfe29cdfbe9250f31 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 27 Oct 2015 16:59:57 -0700 Subject: [PATCH 2/2] fix it and accept new baselines --- src/compiler/checker.ts | 12 +-- .../reference/typeGuardDuplicateGuards.js | 17 ++++ .../typeGuardDuplicateGuards.symbols | 48 +++++++++++ .../reference/typeGuardDuplicateGuards.types | 84 +++++++++++++++++++ 4 files changed, 155 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/typeGuardDuplicateGuards.js create mode 100644 tests/baselines/reference/typeGuardDuplicateGuards.symbols create mode 100644 tests/baselines/reference/typeGuardDuplicateGuards.types diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5370e7c4f027d..45dfd856ec84a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6395,22 +6395,22 @@ namespace ts { return narrowType(narrowType(type, expr.left, /*assumeTrue*/ true), expr.right, /*assumeTrue*/ true); } else { - // The assumed result is false. This means either the first operand was false, or the first operand was true - // and the second operand was false. We narrow with those assumptions and union the two resulting types. + // The assumed result is false. This means either the first operand was false, or + // the second operand was false. We narrow with those assumptions and union the two resulting types. return getUnionType([ narrowType(type, expr.left, /*assumeTrue*/ false), - narrowType(narrowType(type, expr.left, /*assumeTrue*/ true), expr.right, /*assumeTrue*/ false) + narrowType(type, expr.right, /*assumeTrue*/ false) ]); } } function narrowTypeByOr(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { if (assumeTrue) { - // The assumed result is true. This means either the first operand was true, or the first operand was false - // and the second operand was true. We narrow with those assumptions and union the two resulting types. + // The assumed result is true. This means either the first operand was true, or + // the second operand was true. We narrow with those assumptions and union the two resulting types. return getUnionType([ narrowType(type, expr.left, /*assumeTrue*/ true), - narrowType(narrowType(type, expr.left, /*assumeTrue*/ false), expr.right, /*assumeTrue*/ true) + narrowType(type, expr.right, /*assumeTrue*/ true) ]); } else { diff --git a/tests/baselines/reference/typeGuardDuplicateGuards.js b/tests/baselines/reference/typeGuardDuplicateGuards.js new file mode 100644 index 0000000000000..50a2e1b9768cd --- /dev/null +++ b/tests/baselines/reference/typeGuardDuplicateGuards.js @@ -0,0 +1,17 @@ +//// [typeGuardDuplicateGuards.ts] +var x: string|number; + +var r1 = typeof x === "string" && typeof x === "string" ? x.substr : x.toFixed; + +var r2 = !(typeof x === "string" && typeof x === "string") ? x.toFixed : x.substr; + +var r3 = typeof x === "string" || typeof x === "string" ? x.substr : x.toFixed; + +var r4 = !(typeof x === "string" || typeof x === "string") ? x.toFixed : x.substr; + +//// [typeGuardDuplicateGuards.js] +var x; +var r1 = typeof x === "string" && typeof x === "string" ? x.substr : x.toFixed; +var r2 = !(typeof x === "string" && typeof x === "string") ? x.toFixed : x.substr; +var r3 = typeof x === "string" || typeof x === "string" ? x.substr : x.toFixed; +var r4 = !(typeof x === "string" || typeof x === "string") ? x.toFixed : x.substr; diff --git a/tests/baselines/reference/typeGuardDuplicateGuards.symbols b/tests/baselines/reference/typeGuardDuplicateGuards.symbols new file mode 100644 index 0000000000000..93040d3b98a57 --- /dev/null +++ b/tests/baselines/reference/typeGuardDuplicateGuards.symbols @@ -0,0 +1,48 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardDuplicateGuards.ts === +var x: string|number; +>x : Symbol(x, Decl(typeGuardDuplicateGuards.ts, 0, 3)) + +var r1 = typeof x === "string" && typeof x === "string" ? x.substr : x.toFixed; +>r1 : Symbol(r1, Decl(typeGuardDuplicateGuards.ts, 2, 3)) +>x : Symbol(x, Decl(typeGuardDuplicateGuards.ts, 0, 3)) +>x : Symbol(x, Decl(typeGuardDuplicateGuards.ts, 0, 3)) +>x.substr : Symbol(String.substr, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(typeGuardDuplicateGuards.ts, 0, 3)) +>substr : Symbol(String.substr, Decl(lib.d.ts, --, --)) +>x.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(typeGuardDuplicateGuards.ts, 0, 3)) +>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) + +var r2 = !(typeof x === "string" && typeof x === "string") ? x.toFixed : x.substr; +>r2 : Symbol(r2, Decl(typeGuardDuplicateGuards.ts, 4, 3)) +>x : Symbol(x, Decl(typeGuardDuplicateGuards.ts, 0, 3)) +>x : Symbol(x, Decl(typeGuardDuplicateGuards.ts, 0, 3)) +>x.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(typeGuardDuplicateGuards.ts, 0, 3)) +>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>x.substr : Symbol(String.substr, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(typeGuardDuplicateGuards.ts, 0, 3)) +>substr : Symbol(String.substr, Decl(lib.d.ts, --, --)) + +var r3 = typeof x === "string" || typeof x === "string" ? x.substr : x.toFixed; +>r3 : Symbol(r3, Decl(typeGuardDuplicateGuards.ts, 6, 3)) +>x : Symbol(x, Decl(typeGuardDuplicateGuards.ts, 0, 3)) +>x : Symbol(x, Decl(typeGuardDuplicateGuards.ts, 0, 3)) +>x.substr : Symbol(String.substr, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(typeGuardDuplicateGuards.ts, 0, 3)) +>substr : Symbol(String.substr, Decl(lib.d.ts, --, --)) +>x.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(typeGuardDuplicateGuards.ts, 0, 3)) +>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) + +var r4 = !(typeof x === "string" || typeof x === "string") ? x.toFixed : x.substr; +>r4 : Symbol(r4, Decl(typeGuardDuplicateGuards.ts, 8, 3)) +>x : Symbol(x, Decl(typeGuardDuplicateGuards.ts, 0, 3)) +>x : Symbol(x, Decl(typeGuardDuplicateGuards.ts, 0, 3)) +>x.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(typeGuardDuplicateGuards.ts, 0, 3)) +>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>x.substr : Symbol(String.substr, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(typeGuardDuplicateGuards.ts, 0, 3)) +>substr : Symbol(String.substr, Decl(lib.d.ts, --, --)) + diff --git a/tests/baselines/reference/typeGuardDuplicateGuards.types b/tests/baselines/reference/typeGuardDuplicateGuards.types new file mode 100644 index 0000000000000..d3303d46b19c9 --- /dev/null +++ b/tests/baselines/reference/typeGuardDuplicateGuards.types @@ -0,0 +1,84 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardDuplicateGuards.ts === +var x: string|number; +>x : string | number + +var r1 = typeof x === "string" && typeof x === "string" ? x.substr : x.toFixed; +>r1 : (from: number, length?: number) => string +>typeof x === "string" && typeof x === "string" ? x.substr : x.toFixed : (from: number, length?: number) => string +>typeof x === "string" && typeof x === "string" : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : string | number +>"string" : string +>typeof x === "string" : boolean +>typeof x : string +>x : string +>"string" : string +>x.substr : (from: number, length?: number) => string +>x : string +>substr : (from: number, length?: number) => string +>x.toFixed : (fractionDigits?: number) => string +>x : number +>toFixed : (fractionDigits?: number) => string + +var r2 = !(typeof x === "string" && typeof x === "string") ? x.toFixed : x.substr; +>r2 : (fractionDigits?: number) => string +>!(typeof x === "string" && typeof x === "string") ? x.toFixed : x.substr : (fractionDigits?: number) => string +>!(typeof x === "string" && typeof x === "string") : boolean +>(typeof x === "string" && typeof x === "string") : boolean +>typeof x === "string" && typeof x === "string" : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : string | number +>"string" : string +>typeof x === "string" : boolean +>typeof x : string +>x : string +>"string" : string +>x.toFixed : (fractionDigits?: number) => string +>x : number +>toFixed : (fractionDigits?: number) => string +>x.substr : (from: number, length?: number) => string +>x : string +>substr : (from: number, length?: number) => string + +var r3 = typeof x === "string" || typeof x === "string" ? x.substr : x.toFixed; +>r3 : (from: number, length?: number) => string +>typeof x === "string" || typeof x === "string" ? x.substr : x.toFixed : (from: number, length?: number) => string +>typeof x === "string" || typeof x === "string" : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : string | number +>"string" : string +>typeof x === "string" : boolean +>typeof x : string +>x : number +>"string" : string +>x.substr : (from: number, length?: number) => string +>x : string +>substr : (from: number, length?: number) => string +>x.toFixed : (fractionDigits?: number) => string +>x : number +>toFixed : (fractionDigits?: number) => string + +var r4 = !(typeof x === "string" || typeof x === "string") ? x.toFixed : x.substr; +>r4 : (fractionDigits?: number) => string +>!(typeof x === "string" || typeof x === "string") ? x.toFixed : x.substr : (fractionDigits?: number) => string +>!(typeof x === "string" || typeof x === "string") : boolean +>(typeof x === "string" || typeof x === "string") : boolean +>typeof x === "string" || typeof x === "string" : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : string | number +>"string" : string +>typeof x === "string" : boolean +>typeof x : string +>x : number +>"string" : string +>x.toFixed : (fractionDigits?: number) => string +>x : number +>toFixed : (fractionDigits?: number) => string +>x.substr : (from: number, length?: number) => string +>x : string +>substr : (from: number, length?: number) => string +