fix typefacts of intersection (#47583)

This commit is contained in:
Gabriela Araujo Britto 2022-02-01 17:10:43 -03:00 committed by GitHub
parent 21bbb576ad
commit 46e7ab4dbf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 157 additions and 2 deletions

View File

@ -135,7 +135,7 @@ namespace ts {
AllTypeofNE = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | NEUndefined,
EmptyObjectFacts = All,
// Masks
OrFactsMask = TypeofEQFunction | TypeofEQObject | TypeofNEObject,
OrFactsMask = TypeofEQFunction | TypeofNEObject,
AndFactsMask = All & ~OrFactsMask,
}
@ -22961,7 +22961,10 @@ namespace ts {
(type === falseType || type === regularFalseType) ? TypeFacts.FalseStrictFacts : TypeFacts.TrueStrictFacts :
(type === falseType || type === regularFalseType) ? TypeFacts.FalseFacts : TypeFacts.TrueFacts;
}
if (flags & TypeFlags.Object && !ignoreObjects) {
if (flags & TypeFlags.Object) {
if (ignoreObjects) {
return TypeFacts.AndFactsMask; // This is the identity element for computing type facts of intersection.
}
return getObjectFlags(type) & ObjectFlags.Anonymous && isEmptyObjectType(type as ObjectType) ?
strictNullChecks ? TypeFacts.EmptyObjectStrictFacts : TypeFacts.EmptyObjectFacts :
isFunctionObjectType(type as ObjectType) ?

View File

@ -18,6 +18,12 @@ function f2<T>(x: (T & F) | T & string) {
else {
x;
}
}
function f3(x: { _foo: number } & number) {
if (typeof x === "function") {
x;
}
}
//// [narrowingTypeofFunction.js]
@ -38,3 +44,8 @@ function f2(x) {
x;
}
}
function f3(x) {
if (typeof x === "function") {
x;
}
}

View File

@ -43,3 +43,16 @@ function f2<T>(x: (T & F) | T & string) {
>x : Symbol(x, Decl(narrowingTypeofFunction.ts, 12, 15))
}
}
function f3(x: { _foo: number } & number) {
>f3 : Symbol(f3, Decl(narrowingTypeofFunction.ts, 19, 1))
>x : Symbol(x, Decl(narrowingTypeofFunction.ts, 21, 12))
>_foo : Symbol(_foo, Decl(narrowingTypeofFunction.ts, 21, 16))
if (typeof x === "function") {
>x : Symbol(x, Decl(narrowingTypeofFunction.ts, 21, 12))
x;
>x : Symbol(x, Decl(narrowingTypeofFunction.ts, 21, 12))
}
}

View File

@ -42,3 +42,19 @@ function f2<T>(x: (T & F) | T & string) {
>x : T & string
}
}
function f3(x: { _foo: number } & number) {
>f3 : (x: { _foo: number;} & number) => void
>x : { _foo: number; } & number
>_foo : number
if (typeof x === "function") {
>typeof x === "function" : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : { _foo: number; } & number
>"function" : "function"
x;
>x : never
}
}

View File

@ -0,0 +1,27 @@
//// [narrowingTypeofObject.ts]
interface F { (): string }
function test(x: number & { _foo: string }) {
if (typeof x === 'object') {
x;
}
}
function f1(x: F & { foo: number }) {
if (typeof x !== "object") {
x;
}
}
//// [narrowingTypeofObject.js]
"use strict";
function test(x) {
if (typeof x === 'object') {
x;
}
}
function f1(x) {
if (typeof x !== "object") {
x;
}
}

View File

@ -0,0 +1,30 @@
=== tests/cases/compiler/narrowingTypeofObject.ts ===
interface F { (): string }
>F : Symbol(F, Decl(narrowingTypeofObject.ts, 0, 0))
function test(x: number & { _foo: string }) {
>test : Symbol(test, Decl(narrowingTypeofObject.ts, 0, 26))
>x : Symbol(x, Decl(narrowingTypeofObject.ts, 2, 14))
>_foo : Symbol(_foo, Decl(narrowingTypeofObject.ts, 2, 27))
if (typeof x === 'object') {
>x : Symbol(x, Decl(narrowingTypeofObject.ts, 2, 14))
x;
>x : Symbol(x, Decl(narrowingTypeofObject.ts, 2, 14))
}
}
function f1(x: F & { foo: number }) {
>f1 : Symbol(f1, Decl(narrowingTypeofObject.ts, 6, 1))
>x : Symbol(x, Decl(narrowingTypeofObject.ts, 8, 12))
>F : Symbol(F, Decl(narrowingTypeofObject.ts, 0, 0))
>foo : Symbol(foo, Decl(narrowingTypeofObject.ts, 8, 20))
if (typeof x !== "object") {
>x : Symbol(x, Decl(narrowingTypeofObject.ts, 8, 12))
x;
>x : Symbol(x, Decl(narrowingTypeofObject.ts, 8, 12))
}
}

View File

@ -0,0 +1,34 @@
=== tests/cases/compiler/narrowingTypeofObject.ts ===
interface F { (): string }
function test(x: number & { _foo: string }) {
>test : (x: number & { _foo: string;}) => void
>x : number & { _foo: string; }
>_foo : string
if (typeof x === 'object') {
>typeof x === 'object' : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : number & { _foo: string; }
>'object' : "object"
x;
>x : never
}
}
function f1(x: F & { foo: number }) {
>f1 : (x: F & { foo: number;}) => void
>x : F & { foo: number; }
>foo : number
if (typeof x !== "object") {
>typeof x !== "object" : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : F & { foo: number; }
>"object" : "object"
x;
>x : F & { foo: number; }
}
}

View File

@ -19,4 +19,10 @@ function f2<T>(x: (T & F) | T & string) {
else {
x;
}
}
function f3(x: { _foo: number } & number) {
if (typeof x === "function") {
x;
}
}

View File

@ -0,0 +1,15 @@
// @strict: true
interface F { (): string }
function test(x: number & { _foo: string }) {
if (typeof x === 'object') {
x;
}
}
function f1(x: F & { foo: number }) {
if (typeof x !== "object") {
x;
}
}