Redo in narrowing for intersections (#39637)

* Redo in-narrowing for intersections

Still need to carve out an exception for globalThis

* exempt globalThis from `in` narrowing
This commit is contained in:
Nathan Shively-Sanders 2020-07-30 14:58:22 -07:00 committed by GitHub
parent 32934a9989
commit d3877d294c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 72 additions and 6 deletions

View File

@ -21475,7 +21475,9 @@ 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)
|| isThisTypeParameter(type)
|| type.flags & TypeFlags.Intersection && every((type as IntersectionType).types, t => t.symbol !== globalThisSymbol)) {
const propName = escapeLeadingUnderscores(literal.text);
return filterType(type, t => isTypePresencePossible(t, propName, assumeTrue));
}

View File

@ -19,10 +19,9 @@ tests/cases/compiler/inKeywordTypeguard.ts(74,32): error TS2339: Property 'a' do
tests/cases/compiler/inKeywordTypeguard.ts(82,39): error TS2339: Property 'b' does not exist on type 'A'.
tests/cases/compiler/inKeywordTypeguard.ts(84,39): error TS2339: Property 'a' does not exist on type 'B'.
tests/cases/compiler/inKeywordTypeguard.ts(94,26): error TS2339: Property 'a' does not exist on type 'never'.
tests/cases/compiler/inKeywordTypeguard.ts(103,13): error TS2322: Type '{ a: string; } & { b: string; }' is not assignable to type 'never'.
==== tests/cases/compiler/inKeywordTypeguard.ts (18 errors) ====
==== tests/cases/compiler/inKeywordTypeguard.ts (17 errors) ====
class A { a: string; }
class B { b: string; }
@ -164,8 +163,13 @@ tests/cases/compiler/inKeywordTypeguard.ts(103,13): error TS2322: Type '{ a: str
let s: string = x.a;
} else {
let n: never = x;
~
!!! error TS2322: Type '{ a: string; } & { b: string; }' is not assignable to type 'never'.
}
}
function negativeIntersectionTest() {
if ("ontouchstart" in window) {
window.ontouchstart
} else {
window.ontouchstart
}
}

View File

@ -104,6 +104,13 @@ function positiveIntersectionTest(x: { a: string } & { b: string }) {
let n: never = x;
}
}
function negativeIntersectionTest() {
if ("ontouchstart" in window) {
window.ontouchstart
} else {
window.ontouchstart
}
}
//// [inKeywordTypeguard.js]
@ -245,3 +252,11 @@ function positiveIntersectionTest(x) {
var n = x;
}
}
function negativeIntersectionTest() {
if ("ontouchstart" in window) {
window.ontouchstart;
}
else {
window.ontouchstart;
}
}

View File

@ -261,4 +261,22 @@ function positiveIntersectionTest(x: { a: string } & { b: string }) {
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 98, 34))
}
}
function negativeIntersectionTest() {
>negativeIntersectionTest : Symbol(negativeIntersectionTest, Decl(inKeywordTypeguard.ts, 104, 1))
if ("ontouchstart" in window) {
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
window.ontouchstart
>window.ontouchstart : Symbol(ontouchstart, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
>ontouchstart : Symbol(ontouchstart, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
} else {
window.ontouchstart
>window.ontouchstart : Symbol(ontouchstart, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
>ontouchstart : Symbol(ontouchstart, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
}
}

View File

@ -318,7 +318,27 @@ function positiveIntersectionTest(x: { a: string } & { b: string }) {
} else {
let n: never = x;
>n : never
>x : { a: string; } & { b: string; }
>x : never
}
}
function negativeIntersectionTest() {
>negativeIntersectionTest : () => void
if ("ontouchstart" in window) {
>"ontouchstart" in window : boolean
>"ontouchstart" : "ontouchstart"
>window : Window & typeof globalThis
window.ontouchstart
>window.ontouchstart : ((this: GlobalEventHandlers, ev: TouchEvent) => any) & ((this: Window, ev: TouchEvent) => any)
>window : Window & typeof globalThis
>ontouchstart : ((this: GlobalEventHandlers, ev: TouchEvent) => any) & ((this: Window, ev: TouchEvent) => any)
} else {
window.ontouchstart
>window.ontouchstart : ((this: GlobalEventHandlers, ev: TouchEvent) => any) & ((this: Window, ev: TouchEvent) => any)
>window : Window & typeof globalThis
>ontouchstart : ((this: GlobalEventHandlers, ev: TouchEvent) => any) & ((this: Window, ev: TouchEvent) => any)
}
}

View File

@ -103,3 +103,10 @@ function positiveIntersectionTest(x: { a: string } & { b: string }) {
let n: never = x;
}
}
function negativeIntersectionTest() {
if ("ontouchstart" in window) {
window.ontouchstart
} else {
window.ontouchstart
}
}