From fb0bdb9379489b479e1e7b35ca558991360cd57a Mon Sep 17 00:00:00 2001 From: pizzacat83 <17941141+pizzacat83@users.noreply.github.com> Date: Sat, 29 Feb 2020 01:23:28 +0900 Subject: [PATCH] support 'in' type guard of intersections --- src/compiler/checker.ts | 2 +- .../reference/inKeywordTypeguard.errors.txt | 11 +++++++- .../baselines/reference/inKeywordTypeguard.js | 19 +++++++++++++- .../reference/inKeywordTypeguard.symbols | 23 +++++++++++++++++ .../reference/inKeywordTypeguard.types | 25 +++++++++++++++++++ tests/cases/compiler/inKeywordTypeguard.ts | 10 +++++++- 6 files changed, 86 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1b2e6931e02c4..0b3dd1974ce6c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20028,7 +20028,7 @@ namespace ts { } function narrowByInKeyword(type: Type, literal: LiteralExpression, assumeTrue: boolean) { - if (type.flags & (TypeFlags.Union | TypeFlags.Object) || isThisTypeParameter(type)) { + if (type.flags & (TypeFlags.Union | TypeFlags.Object | TypeFlags.Intersection) || isThisTypeParameter(type)) { const propName = escapeLeadingUnderscores(literal.text); return filterType(type, t => isTypePresencePossible(t, propName, assumeTrue)); } diff --git a/tests/baselines/reference/inKeywordTypeguard.errors.txt b/tests/baselines/reference/inKeywordTypeguard.errors.txt index 914daf42a7e98..f5885acfc8835 100644 --- a/tests/baselines/reference/inKeywordTypeguard.errors.txt +++ b/tests/baselines/reference/inKeywordTypeguard.errors.txt @@ -156,4 +156,13 @@ tests/cases/compiler/inKeywordTypeguard.ts(94,26): error TS2339: Property 'a' do !!! error TS2339: Property 'a' does not exist on type 'never'. } } - } \ No newline at end of file + } + + function positiveIntersectionTest(x: { a: string } & { b: string }) { + if ("a" in x) { + let s: string = x.a; + } else { + let n: never = x; + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/inKeywordTypeguard.js b/tests/baselines/reference/inKeywordTypeguard.js index 41ad27f96dff5..83499d7f54e3d 100644 --- a/tests/baselines/reference/inKeywordTypeguard.js +++ b/tests/baselines/reference/inKeywordTypeguard.js @@ -95,7 +95,16 @@ class UnreachableCodeDetection { let y = this.a; } } -} +} + +function positiveIntersectionTest(x: { a: string } & { b: string }) { + if ("a" in x) { + let s: string = x.a; + } else { + let n: never = x; + } +} + //// [inKeywordTypeguard.js] var A = /** @class */ (function () { @@ -228,3 +237,11 @@ var UnreachableCodeDetection = /** @class */ (function () { }; return UnreachableCodeDetection; }()); +function positiveIntersectionTest(x) { + if ("a" in x) { + var s = x.a; + } + else { + var n = x; + } +} diff --git a/tests/baselines/reference/inKeywordTypeguard.symbols b/tests/baselines/reference/inKeywordTypeguard.symbols index c73f6f4901de5..ff79a4aa54efb 100644 --- a/tests/baselines/reference/inKeywordTypeguard.symbols +++ b/tests/baselines/reference/inKeywordTypeguard.symbols @@ -239,3 +239,26 @@ class UnreachableCodeDetection { } } } + +function positiveIntersectionTest(x: { a: string } & { b: string }) { +>positiveIntersectionTest : Symbol(positiveIntersectionTest, Decl(inKeywordTypeguard.ts, 96, 1)) +>x : Symbol(x, Decl(inKeywordTypeguard.ts, 98, 34)) +>a : Symbol(a, Decl(inKeywordTypeguard.ts, 98, 38)) +>b : Symbol(b, Decl(inKeywordTypeguard.ts, 98, 54)) + + if ("a" in x) { +>x : Symbol(x, Decl(inKeywordTypeguard.ts, 98, 34)) + + let s: string = x.a; +>s : Symbol(s, Decl(inKeywordTypeguard.ts, 100, 11)) +>x.a : Symbol(a, Decl(inKeywordTypeguard.ts, 98, 38)) +>x : Symbol(x, Decl(inKeywordTypeguard.ts, 98, 34)) +>a : Symbol(a, Decl(inKeywordTypeguard.ts, 98, 38)) + + } else { + let n: never = x; +>n : Symbol(n, Decl(inKeywordTypeguard.ts, 102, 11)) +>x : Symbol(x, Decl(inKeywordTypeguard.ts, 98, 34)) + } +} + diff --git a/tests/baselines/reference/inKeywordTypeguard.types b/tests/baselines/reference/inKeywordTypeguard.types index 39c4054057838..ccb27f5c9b698 100644 --- a/tests/baselines/reference/inKeywordTypeguard.types +++ b/tests/baselines/reference/inKeywordTypeguard.types @@ -297,3 +297,28 @@ class UnreachableCodeDetection { } } } + +function positiveIntersectionTest(x: { a: string } & { b: string }) { +>positiveIntersectionTest : (x: { a: string; } & { b: string; }) => void +>x : { a: string; } & { b: string; } +>a : string +>b : string + + if ("a" in x) { +>"a" in x : boolean +>"a" : "a" +>x : { a: string; } & { b: string; } + + let s: string = x.a; +>s : string +>x.a : string +>x : { a: string; } & { b: string; } +>a : string + + } else { + let n: never = x; +>n : never +>x : never + } +} + diff --git a/tests/cases/compiler/inKeywordTypeguard.ts b/tests/cases/compiler/inKeywordTypeguard.ts index bbab20afc6f41..620aa401b252e 100644 --- a/tests/cases/compiler/inKeywordTypeguard.ts +++ b/tests/cases/compiler/inKeywordTypeguard.ts @@ -94,4 +94,12 @@ class UnreachableCodeDetection { let y = this.a; } } -} \ No newline at end of file +} + +function positiveIntersectionTest(x: { a: string } & { b: string }) { + if ("a" in x) { + let s: string = x.a; + } else { + let n: never = x; + } +}