Fixed an issue with in not being able to be used on narrowed down expression of a generic nullable type (#51502)

* Fixed an issue with `in` not being able to be used on narrowed down expression of a generic nullable type

* Add another test case from a new issue

* Move the fix to `hasEmptyObjectIntersection`
This commit is contained in:
Mateusz Burzyński 2022-11-22 07:03:58 +01:00 committed by GitHub
parent 12d7e4bdbf
commit 5cd2d975c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 191 additions and 1 deletions

View File

@ -34998,7 +34998,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
function hasEmptyObjectIntersection(type: Type): boolean {
return someType(type, t => t === unknownEmptyObjectType || !!(t.flags & TypeFlags.Intersection) && some((t as IntersectionType).types, isEmptyAnonymousObjectType));
return someType(type, t => t === unknownEmptyObjectType || !!(t.flags & TypeFlags.Intersection) && isEmptyAnonymousObjectType(getBaseConstraintOrType(t)));
}
function checkInExpression(left: Expression, right: Expression, leftType: Type, rightType: Type): Type {

View File

@ -420,4 +420,16 @@ tests/cases/compiler/inKeywordTypeguard.ts(186,21): error TS2322: Type 'T' is no
const checkIsTouchDevice = () =>
"ontouchstart" in window || "msMaxTouchPoints" in window.navigator;
// Repro from #51501
function isHTMLTable<T extends object | null>(table: T): boolean {
return !!table && 'html' in table;
}
// Repro from #51549
const f = <P extends object>(a: P & {}) => {
"foo" in a;
};

View File

@ -341,6 +341,18 @@ function foo<A>(value: A) {
const checkIsTouchDevice = () =>
"ontouchstart" in window || "msMaxTouchPoints" in window.navigator;
// Repro from #51501
function isHTMLTable<T extends object | null>(table: T): boolean {
return !!table && 'html' in table;
}
// Repro from #51549
const f = <P extends object>(a: P & {}) => {
"foo" in a;
};
//// [inKeywordTypeguard.js]
@ -655,3 +667,11 @@ function foo(value) {
}
// Repro from #50954
const checkIsTouchDevice = () => "ontouchstart" in window || "msMaxTouchPoints" in window.navigator;
// Repro from #51501
function isHTMLTable(table) {
return !!table && 'html' in table;
}
// Repro from #51549
const f = (a) => {
"foo" in a;
};

View File

@ -853,3 +853,29 @@ const checkIsTouchDevice = () =>
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
>navigator : Symbol(navigator, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
// Repro from #51501
function isHTMLTable<T extends object | null>(table: T): boolean {
>isHTMLTable : Symbol(isHTMLTable, Decl(inKeywordTypeguard.ts, 341, 71))
>T : Symbol(T, Decl(inKeywordTypeguard.ts, 345, 21))
>table : Symbol(table, Decl(inKeywordTypeguard.ts, 345, 46))
>T : Symbol(T, Decl(inKeywordTypeguard.ts, 345, 21))
return !!table && 'html' in table;
>table : Symbol(table, Decl(inKeywordTypeguard.ts, 345, 46))
>table : Symbol(table, Decl(inKeywordTypeguard.ts, 345, 46))
}
// Repro from #51549
const f = <P extends object>(a: P & {}) => {
>f : Symbol(f, Decl(inKeywordTypeguard.ts, 351, 5))
>P : Symbol(P, Decl(inKeywordTypeguard.ts, 351, 11))
>a : Symbol(a, Decl(inKeywordTypeguard.ts, 351, 29))
>P : Symbol(P, Decl(inKeywordTypeguard.ts, 351, 11))
"foo" in a;
>a : Symbol(a, Decl(inKeywordTypeguard.ts, 351, 29))
};

View File

@ -1056,3 +1056,34 @@ const checkIsTouchDevice = () =>
>window : Window & typeof globalThis
>navigator : Navigator
// Repro from #51501
function isHTMLTable<T extends object | null>(table: T): boolean {
>isHTMLTable : <T extends object>(table: T) => boolean
>null : null
>table : T
return !!table && 'html' in table;
>!!table && 'html' in table : boolean
>!!table : boolean
>!table : boolean
>table : T
>'html' in table : boolean
>'html' : "html"
>table : T
}
// Repro from #51549
const f = <P extends object>(a: P & {}) => {
>f : <P extends object>(a: P & {}) => void
><P extends object>(a: P & {}) => { "foo" in a;} : <P extends object>(a: P & {}) => void
>a : P & {}
"foo" in a;
>"foo" in a : boolean
>"foo" : "foo"
>a : P & {}
};

View File

@ -440,4 +440,16 @@ tests/cases/compiler/inKeywordTypeguard.ts(186,21): error TS2638: Type 'NonNulla
const checkIsTouchDevice = () =>
"ontouchstart" in window || "msMaxTouchPoints" in window.navigator;
// Repro from #51501
function isHTMLTable<T extends object | null>(table: T): boolean {
return !!table && 'html' in table;
}
// Repro from #51549
const f = <P extends object>(a: P & {}) => {
"foo" in a;
};

View File

@ -341,6 +341,18 @@ function foo<A>(value: A) {
const checkIsTouchDevice = () =>
"ontouchstart" in window || "msMaxTouchPoints" in window.navigator;
// Repro from #51501
function isHTMLTable<T extends object | null>(table: T): boolean {
return !!table && 'html' in table;
}
// Repro from #51549
const f = <P extends object>(a: P & {}) => {
"foo" in a;
};
//// [inKeywordTypeguard.js]
@ -656,3 +668,11 @@ function foo(value) {
}
// Repro from #50954
const checkIsTouchDevice = () => "ontouchstart" in window || "msMaxTouchPoints" in window.navigator;
// Repro from #51501
function isHTMLTable(table) {
return !!table && 'html' in table;
}
// Repro from #51549
const f = (a) => {
"foo" in a;
};

View File

@ -853,3 +853,29 @@ const checkIsTouchDevice = () =>
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
>navigator : Symbol(navigator, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
// Repro from #51501
function isHTMLTable<T extends object | null>(table: T): boolean {
>isHTMLTable : Symbol(isHTMLTable, Decl(inKeywordTypeguard.ts, 341, 71))
>T : Symbol(T, Decl(inKeywordTypeguard.ts, 345, 21))
>table : Symbol(table, Decl(inKeywordTypeguard.ts, 345, 46))
>T : Symbol(T, Decl(inKeywordTypeguard.ts, 345, 21))
return !!table && 'html' in table;
>table : Symbol(table, Decl(inKeywordTypeguard.ts, 345, 46))
>table : Symbol(table, Decl(inKeywordTypeguard.ts, 345, 46))
}
// Repro from #51549
const f = <P extends object>(a: P & {}) => {
>f : Symbol(f, Decl(inKeywordTypeguard.ts, 351, 5))
>P : Symbol(P, Decl(inKeywordTypeguard.ts, 351, 11))
>a : Symbol(a, Decl(inKeywordTypeguard.ts, 351, 29))
>P : Symbol(P, Decl(inKeywordTypeguard.ts, 351, 11))
"foo" in a;
>a : Symbol(a, Decl(inKeywordTypeguard.ts, 351, 29))
};

View File

@ -1056,3 +1056,34 @@ const checkIsTouchDevice = () =>
>window : Window & typeof globalThis
>navigator : Navigator
// Repro from #51501
function isHTMLTable<T extends object | null>(table: T): boolean {
>isHTMLTable : <T extends object | null>(table: T) => boolean
>null : null
>table : T
return !!table && 'html' in table;
>!!table && 'html' in table : boolean
>!!table : boolean
>!table : boolean
>table : T
>'html' in table : boolean
>'html' : "html"
>table : NonNullable<T>
}
// Repro from #51549
const f = <P extends object>(a: P & {}) => {
>f : <P extends object>(a: P & {}) => void
><P extends object>(a: P & {}) => { "foo" in a;} : <P extends object>(a: P & {}) => void
>a : P & {}
"foo" in a;
>"foo" in a : boolean
>"foo" : "foo"
>a : P & {}
};

View File

@ -343,3 +343,15 @@ function foo<A>(value: A) {
const checkIsTouchDevice = () =>
"ontouchstart" in window || "msMaxTouchPoints" in window.navigator;
// Repro from #51501
function isHTMLTable<T extends object | null>(table: T): boolean {
return !!table && 'html' in table;
}
// Repro from #51549
const f = <P extends object>(a: P & {}) => {
"foo" in a;
};