From 06746efbd9470acde33badc5a9ef85d2c043f9cf Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 13 Dec 2021 09:05:55 -0800 Subject: [PATCH] Revert change to getFalsyFlags (#47125) * Revert change to getFalsyFlags * Add regression test --- src/compiler/checker.ts | 2 +- .../reference/spreadObjectOrFalsy.errors.txt | 18 ++++++++ .../reference/spreadObjectOrFalsy.js | 39 +++++++++++++++++ .../reference/spreadObjectOrFalsy.symbols | 43 +++++++++++++++++++ .../reference/spreadObjectOrFalsy.types | 39 +++++++++++++++++ .../types/spread/spreadObjectOrFalsy.ts | 18 ++++++++ 6 files changed, 158 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a8a92caf90451..590cebef919fb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20893,7 +20893,7 @@ namespace ts { // flags for the string, number, boolean, "", 0, false, void, undefined, or null types respectively. Returns // no flags for all other types (including non-falsy literal types). function getFalsyFlags(type: Type): TypeFlags { - return type.flags & TypeFlags.UnionOrIntersection ? getFalsyFlagsOfTypes((type as UnionType).types) : + return type.flags & TypeFlags.Union ? getFalsyFlagsOfTypes((type as UnionType).types) : type.flags & TypeFlags.StringLiteral ? (type as StringLiteralType).value === "" ? TypeFlags.StringLiteral : 0 : type.flags & TypeFlags.NumberLiteral ? (type as NumberLiteralType).value === 0 ? TypeFlags.NumberLiteral : 0 : type.flags & TypeFlags.BigIntLiteral ? isZeroBigInt(type as BigIntLiteralType) ? TypeFlags.BigIntLiteral : 0 : diff --git a/tests/baselines/reference/spreadObjectOrFalsy.errors.txt b/tests/baselines/reference/spreadObjectOrFalsy.errors.txt index 02c3a9aaf0cd5..87f8fa1d7e741 100644 --- a/tests/baselines/reference/spreadObjectOrFalsy.errors.txt +++ b/tests/baselines/reference/spreadObjectOrFalsy.errors.txt @@ -39,4 +39,22 @@ tests/cases/conformance/types/spread/spreadObjectOrFalsy.ts(10,14): error TS2698 ...z }; } + + // Repro from #47028 + + interface DatafulFoo { + data: T; + } + + class Foo { + data: T | undefined; + bar() { + if (this.hasData()) { + this.data.toLocaleLowerCase(); + } + } + hasData(): this is DatafulFoo { + return true; + } + } \ No newline at end of file diff --git a/tests/baselines/reference/spreadObjectOrFalsy.js b/tests/baselines/reference/spreadObjectOrFalsy.js index b53d4ca23c97d..9aae56dc08562 100644 --- a/tests/baselines/reference/spreadObjectOrFalsy.js +++ b/tests/baselines/reference/spreadObjectOrFalsy.js @@ -31,6 +31,24 @@ function g1(a: A) { ...z }; } + +// Repro from #47028 + +interface DatafulFoo { + data: T; +} + +class Foo { + data: T | undefined; + bar() { + if (this.hasData()) { + this.data.toLocaleLowerCase(); + } + } + hasData(): this is DatafulFoo { + return true; + } +} //// [spreadObjectOrFalsy.js] @@ -69,6 +87,19 @@ function g1(a) { var z = a.z; return __assign({}, z); } +var Foo = /** @class */ (function () { + function Foo() { + } + Foo.prototype.bar = function () { + if (this.hasData()) { + this.data.toLocaleLowerCase(); + } + }; + Foo.prototype.hasData = function () { + return true; + }; + return Foo; +}()); //// [spreadObjectOrFalsy.d.ts] @@ -81,3 +112,11 @@ declare function f6(a: T): T; declare function g1(a: A): (T | undefined) & T; +interface DatafulFoo { + data: T; +} +declare class Foo { + data: T | undefined; + bar(): void; + hasData(): this is DatafulFoo; +} diff --git a/tests/baselines/reference/spreadObjectOrFalsy.symbols b/tests/baselines/reference/spreadObjectOrFalsy.symbols index f89f5387fa955..59c4b2aadf1b4 100644 --- a/tests/baselines/reference/spreadObjectOrFalsy.symbols +++ b/tests/baselines/reference/spreadObjectOrFalsy.symbols @@ -85,3 +85,46 @@ function g1(a: A) { }; } +// Repro from #47028 + +interface DatafulFoo { +>DatafulFoo : Symbol(DatafulFoo, Decl(spreadObjectOrFalsy.ts, 31, 1)) +>T : Symbol(T, Decl(spreadObjectOrFalsy.ts, 35, 21)) + + data: T; +>data : Symbol(DatafulFoo.data, Decl(spreadObjectOrFalsy.ts, 35, 25)) +>T : Symbol(T, Decl(spreadObjectOrFalsy.ts, 35, 21)) +} + +class Foo { +>Foo : Symbol(Foo, Decl(spreadObjectOrFalsy.ts, 37, 1)) +>T : Symbol(T, Decl(spreadObjectOrFalsy.ts, 39, 10)) + + data: T | undefined; +>data : Symbol(Foo.data, Decl(spreadObjectOrFalsy.ts, 39, 29)) +>T : Symbol(T, Decl(spreadObjectOrFalsy.ts, 39, 10)) + + bar() { +>bar : Symbol(Foo.bar, Decl(spreadObjectOrFalsy.ts, 40, 24)) + + if (this.hasData()) { +>this.hasData : Symbol(Foo.hasData, Decl(spreadObjectOrFalsy.ts, 45, 5)) +>this : Symbol(Foo, Decl(spreadObjectOrFalsy.ts, 37, 1)) +>hasData : Symbol(Foo.hasData, Decl(spreadObjectOrFalsy.ts, 45, 5)) + + this.data.toLocaleLowerCase(); +>this.data.toLocaleLowerCase : Symbol(String.toLocaleLowerCase, Decl(lib.es5.d.ts, --, --)) +>this.data : Symbol(data, Decl(spreadObjectOrFalsy.ts, 39, 29), Decl(spreadObjectOrFalsy.ts, 35, 25)) +>data : Symbol(data, Decl(spreadObjectOrFalsy.ts, 39, 29), Decl(spreadObjectOrFalsy.ts, 35, 25)) +>toLocaleLowerCase : Symbol(String.toLocaleLowerCase, Decl(lib.es5.d.ts, --, --)) + } + } + hasData(): this is DatafulFoo { +>hasData : Symbol(Foo.hasData, Decl(spreadObjectOrFalsy.ts, 45, 5)) +>DatafulFoo : Symbol(DatafulFoo, Decl(spreadObjectOrFalsy.ts, 31, 1)) +>T : Symbol(T, Decl(spreadObjectOrFalsy.ts, 39, 10)) + + return true; + } +} + diff --git a/tests/baselines/reference/spreadObjectOrFalsy.types b/tests/baselines/reference/spreadObjectOrFalsy.types index 279b7cf7b66bc..1b9d54512e9f7 100644 --- a/tests/baselines/reference/spreadObjectOrFalsy.types +++ b/tests/baselines/reference/spreadObjectOrFalsy.types @@ -73,3 +73,42 @@ function g1(a: A) { }; } +// Repro from #47028 + +interface DatafulFoo { + data: T; +>data : T +} + +class Foo { +>Foo : Foo + + data: T | undefined; +>data : T | undefined + + bar() { +>bar : () => void + + if (this.hasData()) { +>this.hasData() : boolean +>this.hasData : () => this is DatafulFoo +>this : this +>hasData : () => this is DatafulFoo + + this.data.toLocaleLowerCase(); +>this.data.toLocaleLowerCase() : string +>this.data.toLocaleLowerCase : (locales?: string | string[] | undefined) => string +>this.data : (T | undefined) & T +>this : this & DatafulFoo +>data : (T | undefined) & T +>toLocaleLowerCase : (locales?: string | string[] | undefined) => string + } + } + hasData(): this is DatafulFoo { +>hasData : () => this is DatafulFoo + + return true; +>true : true + } +} + diff --git a/tests/cases/conformance/types/spread/spreadObjectOrFalsy.ts b/tests/cases/conformance/types/spread/spreadObjectOrFalsy.ts index 86d7357842eac..1606a065dc95f 100644 --- a/tests/cases/conformance/types/spread/spreadObjectOrFalsy.ts +++ b/tests/cases/conformance/types/spread/spreadObjectOrFalsy.ts @@ -33,3 +33,21 @@ function g1(a: A) { ...z }; } + +// Repro from #47028 + +interface DatafulFoo { + data: T; +} + +class Foo { + data: T | undefined; + bar() { + if (this.hasData()) { + this.data.toLocaleLowerCase(); + } + } + hasData(): this is DatafulFoo { + return true; + } +}