From dbab46c363fba4ee26a74875de3a2e35925e2de7 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Tue, 18 Aug 2020 11:06:44 -0700 Subject: [PATCH] The falsy part of any/unknown is any/unknown (#39529) --- src/compiler/checker.ts | 2 +- .../anyAndUnknownHaveFalsyComponents.js | 54 +++++++++++++ .../anyAndUnknownHaveFalsyComponents.symbols | 57 ++++++++++++++ .../anyAndUnknownHaveFalsyComponents.types | 75 +++++++++++++++++++ ...xpressionTypecheckingDoesntBlowStack.types | 2 +- .../reference/controlFlowCaching.types | 4 +- .../reference/narrowingTruthyObject.types | 24 +++--- .../anyAndUnknownHaveFalsyComponents.ts | 29 +++++++ 8 files changed, 231 insertions(+), 16 deletions(-) create mode 100644 tests/baselines/reference/anyAndUnknownHaveFalsyComponents.js create mode 100644 tests/baselines/reference/anyAndUnknownHaveFalsyComponents.symbols create mode 100644 tests/baselines/reference/anyAndUnknownHaveFalsyComponents.types create mode 100644 tests/cases/compiler/anyAndUnknownHaveFalsyComponents.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a8f99c8d4b..242e096ce4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18652,7 +18652,7 @@ namespace ts { type.flags & TypeFlags.BigInt ? zeroBigIntType : type === regularFalseType || type === falseType || - type.flags & (TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null) || + type.flags & (TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null | TypeFlags.AnyOrUnknown) || type.flags & TypeFlags.StringLiteral && (type).value === "" || type.flags & TypeFlags.NumberLiteral && (type).value === 0 || type.flags & TypeFlags.BigIntLiteral && isZeroBigInt(type) ? type : diff --git a/tests/baselines/reference/anyAndUnknownHaveFalsyComponents.js b/tests/baselines/reference/anyAndUnknownHaveFalsyComponents.js new file mode 100644 index 0000000000..2d33681fed --- /dev/null +++ b/tests/baselines/reference/anyAndUnknownHaveFalsyComponents.js @@ -0,0 +1,54 @@ +//// [anyAndUnknownHaveFalsyComponents.ts] +declare let x1: any; +const y1 = x1 && 3; + +// #39113 +declare let isTreeHeader1: any; +function foo1() { + return { + display: "block", + ...(isTreeHeader1 && { + display: "flex", + }) + }; +} + +declare let x2: unknown; +const y2 = x2 && 3; + +// #39113 +declare let isTreeHeader2: unknown; +function foo2() { + return { + display: "block", + ...(isTreeHeader1 && { + display: "flex", + }) + }; +} + + +//// [anyAndUnknownHaveFalsyComponents.js] +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var y1 = x1 && 3; +function foo1() { + return __assign({ display: "block" }, (isTreeHeader1 && { + display: "flex" + })); +} +var y2 = x2 && 3; +function foo2() { + return __assign({ display: "block" }, (isTreeHeader1 && { + display: "flex" + })); +} diff --git a/tests/baselines/reference/anyAndUnknownHaveFalsyComponents.symbols b/tests/baselines/reference/anyAndUnknownHaveFalsyComponents.symbols new file mode 100644 index 0000000000..862e3d1455 --- /dev/null +++ b/tests/baselines/reference/anyAndUnknownHaveFalsyComponents.symbols @@ -0,0 +1,57 @@ +=== tests/cases/compiler/anyAndUnknownHaveFalsyComponents.ts === +declare let x1: any; +>x1 : Symbol(x1, Decl(anyAndUnknownHaveFalsyComponents.ts, 0, 11)) + +const y1 = x1 && 3; +>y1 : Symbol(y1, Decl(anyAndUnknownHaveFalsyComponents.ts, 1, 5)) +>x1 : Symbol(x1, Decl(anyAndUnknownHaveFalsyComponents.ts, 0, 11)) + +// #39113 +declare let isTreeHeader1: any; +>isTreeHeader1 : Symbol(isTreeHeader1, Decl(anyAndUnknownHaveFalsyComponents.ts, 4, 11)) + +function foo1() { +>foo1 : Symbol(foo1, Decl(anyAndUnknownHaveFalsyComponents.ts, 4, 31)) + + return { + display: "block", +>display : Symbol(display, Decl(anyAndUnknownHaveFalsyComponents.ts, 6, 10)) + + ...(isTreeHeader1 && { +>isTreeHeader1 : Symbol(isTreeHeader1, Decl(anyAndUnknownHaveFalsyComponents.ts, 4, 11)) + + display: "flex", +>display : Symbol(display, Decl(anyAndUnknownHaveFalsyComponents.ts, 8, 26)) + + }) + }; +} + +declare let x2: unknown; +>x2 : Symbol(x2, Decl(anyAndUnknownHaveFalsyComponents.ts, 14, 11)) + +const y2 = x2 && 3; +>y2 : Symbol(y2, Decl(anyAndUnknownHaveFalsyComponents.ts, 15, 5)) +>x2 : Symbol(x2, Decl(anyAndUnknownHaveFalsyComponents.ts, 14, 11)) + +// #39113 +declare let isTreeHeader2: unknown; +>isTreeHeader2 : Symbol(isTreeHeader2, Decl(anyAndUnknownHaveFalsyComponents.ts, 18, 11)) + +function foo2() { +>foo2 : Symbol(foo2, Decl(anyAndUnknownHaveFalsyComponents.ts, 18, 35)) + + return { + display: "block", +>display : Symbol(display, Decl(anyAndUnknownHaveFalsyComponents.ts, 20, 10)) + + ...(isTreeHeader1 && { +>isTreeHeader1 : Symbol(isTreeHeader1, Decl(anyAndUnknownHaveFalsyComponents.ts, 4, 11)) + + display: "flex", +>display : Symbol(display, Decl(anyAndUnknownHaveFalsyComponents.ts, 22, 26)) + + }) + }; +} + diff --git a/tests/baselines/reference/anyAndUnknownHaveFalsyComponents.types b/tests/baselines/reference/anyAndUnknownHaveFalsyComponents.types new file mode 100644 index 0000000000..34757366c3 --- /dev/null +++ b/tests/baselines/reference/anyAndUnknownHaveFalsyComponents.types @@ -0,0 +1,75 @@ +=== tests/cases/compiler/anyAndUnknownHaveFalsyComponents.ts === +declare let x1: any; +>x1 : any + +const y1 = x1 && 3; +>y1 : any +>x1 && 3 : any +>x1 : any +>3 : 3 + +// #39113 +declare let isTreeHeader1: any; +>isTreeHeader1 : any + +function foo1() { +>foo1 : () => any + + return { +>{ display: "block", ...(isTreeHeader1 && { display: "flex", }) } : any + + display: "block", +>display : string +>"block" : "block" + + ...(isTreeHeader1 && { +>(isTreeHeader1 && { display: "flex", }) : any +>isTreeHeader1 && { display: "flex", } : any +>isTreeHeader1 : any +>{ display: "flex", } : { display: string; } + + display: "flex", +>display : string +>"flex" : "flex" + + }) + }; +} + +declare let x2: unknown; +>x2 : unknown + +const y2 = x2 && 3; +>y2 : unknown +>x2 && 3 : unknown +>x2 : unknown +>3 : 3 + +// #39113 +declare let isTreeHeader2: unknown; +>isTreeHeader2 : unknown + +function foo2() { +>foo2 : () => any + + return { +>{ display: "block", ...(isTreeHeader1 && { display: "flex", }) } : any + + display: "block", +>display : string +>"block" : "block" + + ...(isTreeHeader1 && { +>(isTreeHeader1 && { display: "flex", }) : any +>isTreeHeader1 && { display: "flex", } : any +>isTreeHeader1 : any +>{ display: "flex", } : { display: string; } + + display: "flex", +>display : string +>"flex" : "flex" + + }) + }; +} + diff --git a/tests/baselines/reference/contextualExpressionTypecheckingDoesntBlowStack.types b/tests/baselines/reference/contextualExpressionTypecheckingDoesntBlowStack.types index 3e690f0844..549783e0d3 100644 --- a/tests/baselines/reference/contextualExpressionTypecheckingDoesntBlowStack.types +++ b/tests/baselines/reference/contextualExpressionTypecheckingDoesntBlowStack.types @@ -59,7 +59,7 @@ export default class Operation { >name : any if(innerResult && innerResult.length > 0) { ->innerResult && innerResult.length > 0 : boolean +>innerResult && innerResult.length > 0 : any >innerResult : any >innerResult.length > 0 : boolean >innerResult.length : any diff --git a/tests/baselines/reference/controlFlowCaching.types b/tests/baselines/reference/controlFlowCaching.types index f78de65da5..6af21ab0a3 100644 --- a/tests/baselines/reference/controlFlowCaching.types +++ b/tests/baselines/reference/controlFlowCaching.types @@ -539,8 +539,8 @@ function f(dim, offsets, arr, acommon, centerAnchorLimit, g, has, lin) { >titleRotation = (taTitleOrientation && taTitleOrientation == "away") ? 180 : 0 : 0 | 180 >titleRotation : number >(taTitleOrientation && taTitleOrientation == "away") ? 180 : 0 : 0 | 180 ->(taTitleOrientation && taTitleOrientation == "away") : boolean ->taTitleOrientation && taTitleOrientation == "away" : boolean +>(taTitleOrientation && taTitleOrientation == "away") : any +>taTitleOrientation && taTitleOrientation == "away" : any >taTitleOrientation : any >taTitleOrientation == "away" : boolean >taTitleOrientation : any diff --git a/tests/baselines/reference/narrowingTruthyObject.types b/tests/baselines/reference/narrowingTruthyObject.types index bf8f9ead87..1f1a4a86f5 100644 --- a/tests/baselines/reference/narrowingTruthyObject.types +++ b/tests/baselines/reference/narrowingTruthyObject.types @@ -31,7 +31,7 @@ function foo(x: unknown, b: boolean) { >toString : () => string } if (x && typeof x === 'object') { ->x && typeof x === 'object' : boolean +>x && typeof x === 'object' : unknown >x : unknown >typeof x === 'object' : boolean >typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" @@ -45,7 +45,7 @@ function foo(x: unknown, b: boolean) { >toString : () => string } if (b && x && typeof x === 'object') { ->b && x && typeof x === 'object' : boolean +>b && x && typeof x === 'object' : unknown >b && x : unknown >b : boolean >x : unknown @@ -61,8 +61,8 @@ function foo(x: unknown, b: boolean) { >toString : () => string } if (x && b && typeof x === 'object') { ->x && b && typeof x === 'object' : boolean ->x && b : boolean +>x && b && typeof x === 'object' : unknown +>x && b : unknown >x : unknown >b : boolean >typeof x === 'object' : boolean @@ -77,9 +77,9 @@ function foo(x: unknown, b: boolean) { >toString : () => string } if (x && b && b && typeof x === 'object') { ->x && b && b && typeof x === 'object' : boolean ->x && b && b : boolean ->x && b : boolean +>x && b && b && typeof x === 'object' : unknown +>x && b && b : unknown +>x && b : unknown >x : unknown >b : boolean >b : true @@ -95,9 +95,9 @@ function foo(x: unknown, b: boolean) { >toString : () => string } if (b && b && x && b && b && typeof x === 'object') { ->b && b && x && b && b && typeof x === 'object' : boolean ->b && b && x && b && b : true ->b && b && x && b : true +>b && b && x && b && b && typeof x === 'object' : unknown +>b && b && x && b && b : unknown +>b && b && x && b : unknown >b && b && x : unknown >b && b : boolean >b : boolean @@ -125,8 +125,8 @@ function f1(x: unknown): any { >x : unknown return x && typeof x === 'object' && x.hasOwnProperty('x'); ->x && typeof x === 'object' && x.hasOwnProperty('x') : boolean ->x && typeof x === 'object' : boolean +>x && typeof x === 'object' && x.hasOwnProperty('x') : unknown +>x && typeof x === 'object' : unknown >x : unknown >typeof x === 'object' : boolean >typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" diff --git a/tests/cases/compiler/anyAndUnknownHaveFalsyComponents.ts b/tests/cases/compiler/anyAndUnknownHaveFalsyComponents.ts new file mode 100644 index 0000000000..e04f6d9612 --- /dev/null +++ b/tests/cases/compiler/anyAndUnknownHaveFalsyComponents.ts @@ -0,0 +1,29 @@ +// @strictNullChecks: true + +declare let x1: any; +const y1 = x1 && 3; + +// #39113 +declare let isTreeHeader1: any; +function foo1() { + return { + display: "block", + ...(isTreeHeader1 && { + display: "flex", + }) + }; +} + +declare let x2: unknown; +const y2 = x2 && 3; + +// #39113 +declare let isTreeHeader2: unknown; +function foo2() { + return { + display: "block", + ...(isTreeHeader1 && { + display: "flex", + }) + }; +}