diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 51df774650e8d..a457944e027a7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -25288,14 +25288,19 @@ namespace ts { assumeTrue = !assumeTrue; } const valueType = getTypeOfExpression(value); - if ((type.flags & TypeFlags.Unknown) && assumeTrue && (operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken)) { + if (((type.flags & TypeFlags.Unknown) || isEmptyAnonymousObjectType(type) && !(valueType.flags & TypeFlags.Nullable)) && + assumeTrue && + (operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) + ) { if (valueType.flags & (TypeFlags.Primitive | TypeFlags.NonPrimitive)) { return valueType; } if (valueType.flags & TypeFlags.Object) { return nonPrimitiveType; } - return type; + if (type.flags & TypeFlags.Unknown) { + return type; + } } if (valueType.flags & TypeFlags.Nullable) { if (!strictNullChecks) { diff --git a/tests/baselines/reference/emptyAnonymousObjectNarrowing(strictnullchecks=false).js b/tests/baselines/reference/emptyAnonymousObjectNarrowing(strictnullchecks=false).js new file mode 100644 index 0000000000000..f543db3268926 --- /dev/null +++ b/tests/baselines/reference/emptyAnonymousObjectNarrowing(strictnullchecks=false).js @@ -0,0 +1,139 @@ +//// [emptyAnonymousObjectNarrowing.ts] +declare let nonNull: {}; +if (nonNull === "foo") { + nonNull; +} +else { + nonNull; +} + +declare let obj: { a: string }; +if (nonNull === obj) { + nonNull; +} +else { + nonNull; +} + +function f1(x: T) { + if (nonNull === x) { + nonNull; + } + else { + nonNull; + } +} + +function f2(x: T) { + if (nonNull === x) { + nonNull; + } + else { + nonNull; + } +} + +declare let union: "xyz" | { a: string } | undefined; +if (nonNull === union) { + nonNull; +} +else { + nonNull; +} + +if (nonNull === undefined) { + nonNull; +} +else { + nonNull; +} + +if (nonNull === null) { + nonNull; +} +else { + nonNull; +} + +if (nonNull == undefined) { + nonNull; +} +else { + nonNull; +} + +// Repro from #50567 +const foo = (value: unknown): string => { + if (!value) { + return 'foo'; + } + if (value === 'xyz') { + return value; // Type '{}' is not assignable to type 'string'. + } + return ''; +}; + + +//// [emptyAnonymousObjectNarrowing.js] +if (nonNull === "foo") { + nonNull; +} +else { + nonNull; +} +if (nonNull === obj) { + nonNull; +} +else { + nonNull; +} +function f1(x) { + if (nonNull === x) { + nonNull; + } + else { + nonNull; + } +} +function f2(x) { + if (nonNull === x) { + nonNull; + } + else { + nonNull; + } +} +if (nonNull === union) { + nonNull; +} +else { + nonNull; +} +if (nonNull === undefined) { + nonNull; +} +else { + nonNull; +} +if (nonNull === null) { + nonNull; +} +else { + nonNull; +} +if (nonNull == undefined) { + nonNull; +} +else { + nonNull; +} +// Repro from #50567 +var foo = function (value) { + if (!value) { + return 'foo'; + } + if (value === 'xyz') { + return value; // Type '{}' is not assignable to type 'string'. + } + return ''; +}; diff --git a/tests/baselines/reference/emptyAnonymousObjectNarrowing(strictnullchecks=false).symbols b/tests/baselines/reference/emptyAnonymousObjectNarrowing(strictnullchecks=false).symbols new file mode 100644 index 0000000000000..1cf0efed0782d --- /dev/null +++ b/tests/baselines/reference/emptyAnonymousObjectNarrowing(strictnullchecks=false).symbols @@ -0,0 +1,139 @@ +=== tests/cases/compiler/emptyAnonymousObjectNarrowing.ts === +declare let nonNull: {}; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) + +if (nonNull === "foo") { +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) + + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} +else { + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} + +declare let obj: { a: string }; +>obj : Symbol(obj, Decl(emptyAnonymousObjectNarrowing.ts, 8, 11)) +>a : Symbol(a, Decl(emptyAnonymousObjectNarrowing.ts, 8, 18)) + +if (nonNull === obj) { +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +>obj : Symbol(obj, Decl(emptyAnonymousObjectNarrowing.ts, 8, 11)) + + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} +else { + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} + +function f1(x: T) { +>f1 : Symbol(f1, Decl(emptyAnonymousObjectNarrowing.ts, 14, 1)) +>T : Symbol(T, Decl(emptyAnonymousObjectNarrowing.ts, 16, 12)) +>x : Symbol(x, Decl(emptyAnonymousObjectNarrowing.ts, 16, 15)) +>T : Symbol(T, Decl(emptyAnonymousObjectNarrowing.ts, 16, 12)) + + if (nonNull === x) { +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +>x : Symbol(x, Decl(emptyAnonymousObjectNarrowing.ts, 16, 15)) + + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) + } + else { + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) + } +} + +function f2(x: T) { +>f2 : Symbol(f2, Decl(emptyAnonymousObjectNarrowing.ts, 23, 1)) +>T : Symbol(T, Decl(emptyAnonymousObjectNarrowing.ts, 25, 12)) +>x : Symbol(x, Decl(emptyAnonymousObjectNarrowing.ts, 25, 30)) +>T : Symbol(T, Decl(emptyAnonymousObjectNarrowing.ts, 25, 12)) + + if (nonNull === x) { +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +>x : Symbol(x, Decl(emptyAnonymousObjectNarrowing.ts, 25, 30)) + + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) + } + else { + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) + } +} + +declare let union: "xyz" | { a: string } | undefined; +>union : Symbol(union, Decl(emptyAnonymousObjectNarrowing.ts, 34, 11)) +>a : Symbol(a, Decl(emptyAnonymousObjectNarrowing.ts, 34, 28)) + +if (nonNull === union) { +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +>union : Symbol(union, Decl(emptyAnonymousObjectNarrowing.ts, 34, 11)) + + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} +else { + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} + +if (nonNull === undefined) { +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +>undefined : Symbol(undefined) + + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} +else { + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} + +if (nonNull === null) { +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) + + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} +else { + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} + +if (nonNull == undefined) { +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +>undefined : Symbol(undefined) + + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} +else { + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} + +// Repro from #50567 +const foo = (value: unknown): string => { +>foo : Symbol(foo, Decl(emptyAnonymousObjectNarrowing.ts, 64, 5)) +>value : Symbol(value, Decl(emptyAnonymousObjectNarrowing.ts, 64, 13)) + + if (!value) { +>value : Symbol(value, Decl(emptyAnonymousObjectNarrowing.ts, 64, 13)) + + return 'foo'; + } + if (value === 'xyz') { +>value : Symbol(value, Decl(emptyAnonymousObjectNarrowing.ts, 64, 13)) + + return value; // Type '{}' is not assignable to type 'string'. +>value : Symbol(value, Decl(emptyAnonymousObjectNarrowing.ts, 64, 13)) + } + return ''; +}; + diff --git a/tests/baselines/reference/emptyAnonymousObjectNarrowing(strictnullchecks=false).types b/tests/baselines/reference/emptyAnonymousObjectNarrowing(strictnullchecks=false).types new file mode 100644 index 0000000000000..3ae0ad92788f1 --- /dev/null +++ b/tests/baselines/reference/emptyAnonymousObjectNarrowing(strictnullchecks=false).types @@ -0,0 +1,152 @@ +=== tests/cases/compiler/emptyAnonymousObjectNarrowing.ts === +declare let nonNull: {}; +>nonNull : {} + +if (nonNull === "foo") { +>nonNull === "foo" : boolean +>nonNull : {} +>"foo" : "foo" + + nonNull; +>nonNull : "foo" +} +else { + nonNull; +>nonNull : {} +} + +declare let obj: { a: string }; +>obj : { a: string; } +>a : string + +if (nonNull === obj) { +>nonNull === obj : boolean +>nonNull : {} +>obj : { a: string; } + + nonNull; +>nonNull : object +} +else { + nonNull; +>nonNull : {} +} + +function f1(x: T) { +>f1 : (x: T) => void +>x : T + + if (nonNull === x) { +>nonNull === x : boolean +>nonNull : {} +>x : T + + nonNull; +>nonNull : {} + } + else { + nonNull; +>nonNull : {} + } +} + +function f2(x: T) { +>f2 : (x: T) => void +>x : T + + if (nonNull === x) { +>nonNull === x : boolean +>nonNull : {} +>x : T + + nonNull; +>nonNull : {} + } + else { + nonNull; +>nonNull : {} + } +} + +declare let union: "xyz" | { a: string } | undefined; +>union : { a: string; } | "xyz" +>a : string + +if (nonNull === union) { +>nonNull === union : boolean +>nonNull : {} +>union : { a: string; } | "xyz" + + nonNull; +>nonNull : {} +} +else { + nonNull; +>nonNull : {} +} + +if (nonNull === undefined) { +>nonNull === undefined : boolean +>nonNull : {} +>undefined : undefined + + nonNull; +>nonNull : {} +} +else { + nonNull; +>nonNull : {} +} + +if (nonNull === null) { +>nonNull === null : boolean +>nonNull : {} +>null : null + + nonNull; +>nonNull : {} +} +else { + nonNull; +>nonNull : {} +} + +if (nonNull == undefined) { +>nonNull == undefined : boolean +>nonNull : {} +>undefined : undefined + + nonNull; +>nonNull : {} +} +else { + nonNull; +>nonNull : {} +} + +// Repro from #50567 +const foo = (value: unknown): string => { +>foo : (value: unknown) => string +>(value: unknown): string => { if (!value) { return 'foo'; } if (value === 'xyz') { return value; // Type '{}' is not assignable to type 'string'. } return '';} : (value: unknown) => string +>value : unknown + + if (!value) { +>!value : boolean +>value : unknown + + return 'foo'; +>'foo' : "foo" + } + if (value === 'xyz') { +>value === 'xyz' : boolean +>value : unknown +>'xyz' : "xyz" + + return value; // Type '{}' is not assignable to type 'string'. +>value : "xyz" + } + return ''; +>'' : "" + +}; + diff --git a/tests/baselines/reference/emptyAnonymousObjectNarrowing(strictnullchecks=true).js b/tests/baselines/reference/emptyAnonymousObjectNarrowing(strictnullchecks=true).js new file mode 100644 index 0000000000000..f543db3268926 --- /dev/null +++ b/tests/baselines/reference/emptyAnonymousObjectNarrowing(strictnullchecks=true).js @@ -0,0 +1,139 @@ +//// [emptyAnonymousObjectNarrowing.ts] +declare let nonNull: {}; +if (nonNull === "foo") { + nonNull; +} +else { + nonNull; +} + +declare let obj: { a: string }; +if (nonNull === obj) { + nonNull; +} +else { + nonNull; +} + +function f1(x: T) { + if (nonNull === x) { + nonNull; + } + else { + nonNull; + } +} + +function f2(x: T) { + if (nonNull === x) { + nonNull; + } + else { + nonNull; + } +} + +declare let union: "xyz" | { a: string } | undefined; +if (nonNull === union) { + nonNull; +} +else { + nonNull; +} + +if (nonNull === undefined) { + nonNull; +} +else { + nonNull; +} + +if (nonNull === null) { + nonNull; +} +else { + nonNull; +} + +if (nonNull == undefined) { + nonNull; +} +else { + nonNull; +} + +// Repro from #50567 +const foo = (value: unknown): string => { + if (!value) { + return 'foo'; + } + if (value === 'xyz') { + return value; // Type '{}' is not assignable to type 'string'. + } + return ''; +}; + + +//// [emptyAnonymousObjectNarrowing.js] +if (nonNull === "foo") { + nonNull; +} +else { + nonNull; +} +if (nonNull === obj) { + nonNull; +} +else { + nonNull; +} +function f1(x) { + if (nonNull === x) { + nonNull; + } + else { + nonNull; + } +} +function f2(x) { + if (nonNull === x) { + nonNull; + } + else { + nonNull; + } +} +if (nonNull === union) { + nonNull; +} +else { + nonNull; +} +if (nonNull === undefined) { + nonNull; +} +else { + nonNull; +} +if (nonNull === null) { + nonNull; +} +else { + nonNull; +} +if (nonNull == undefined) { + nonNull; +} +else { + nonNull; +} +// Repro from #50567 +var foo = function (value) { + if (!value) { + return 'foo'; + } + if (value === 'xyz') { + return value; // Type '{}' is not assignable to type 'string'. + } + return ''; +}; diff --git a/tests/baselines/reference/emptyAnonymousObjectNarrowing(strictnullchecks=true).symbols b/tests/baselines/reference/emptyAnonymousObjectNarrowing(strictnullchecks=true).symbols new file mode 100644 index 0000000000000..1cf0efed0782d --- /dev/null +++ b/tests/baselines/reference/emptyAnonymousObjectNarrowing(strictnullchecks=true).symbols @@ -0,0 +1,139 @@ +=== tests/cases/compiler/emptyAnonymousObjectNarrowing.ts === +declare let nonNull: {}; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) + +if (nonNull === "foo") { +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) + + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} +else { + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} + +declare let obj: { a: string }; +>obj : Symbol(obj, Decl(emptyAnonymousObjectNarrowing.ts, 8, 11)) +>a : Symbol(a, Decl(emptyAnonymousObjectNarrowing.ts, 8, 18)) + +if (nonNull === obj) { +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +>obj : Symbol(obj, Decl(emptyAnonymousObjectNarrowing.ts, 8, 11)) + + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} +else { + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} + +function f1(x: T) { +>f1 : Symbol(f1, Decl(emptyAnonymousObjectNarrowing.ts, 14, 1)) +>T : Symbol(T, Decl(emptyAnonymousObjectNarrowing.ts, 16, 12)) +>x : Symbol(x, Decl(emptyAnonymousObjectNarrowing.ts, 16, 15)) +>T : Symbol(T, Decl(emptyAnonymousObjectNarrowing.ts, 16, 12)) + + if (nonNull === x) { +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +>x : Symbol(x, Decl(emptyAnonymousObjectNarrowing.ts, 16, 15)) + + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) + } + else { + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) + } +} + +function f2(x: T) { +>f2 : Symbol(f2, Decl(emptyAnonymousObjectNarrowing.ts, 23, 1)) +>T : Symbol(T, Decl(emptyAnonymousObjectNarrowing.ts, 25, 12)) +>x : Symbol(x, Decl(emptyAnonymousObjectNarrowing.ts, 25, 30)) +>T : Symbol(T, Decl(emptyAnonymousObjectNarrowing.ts, 25, 12)) + + if (nonNull === x) { +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +>x : Symbol(x, Decl(emptyAnonymousObjectNarrowing.ts, 25, 30)) + + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) + } + else { + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) + } +} + +declare let union: "xyz" | { a: string } | undefined; +>union : Symbol(union, Decl(emptyAnonymousObjectNarrowing.ts, 34, 11)) +>a : Symbol(a, Decl(emptyAnonymousObjectNarrowing.ts, 34, 28)) + +if (nonNull === union) { +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +>union : Symbol(union, Decl(emptyAnonymousObjectNarrowing.ts, 34, 11)) + + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} +else { + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} + +if (nonNull === undefined) { +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +>undefined : Symbol(undefined) + + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} +else { + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} + +if (nonNull === null) { +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) + + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} +else { + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} + +if (nonNull == undefined) { +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +>undefined : Symbol(undefined) + + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} +else { + nonNull; +>nonNull : Symbol(nonNull, Decl(emptyAnonymousObjectNarrowing.ts, 0, 11)) +} + +// Repro from #50567 +const foo = (value: unknown): string => { +>foo : Symbol(foo, Decl(emptyAnonymousObjectNarrowing.ts, 64, 5)) +>value : Symbol(value, Decl(emptyAnonymousObjectNarrowing.ts, 64, 13)) + + if (!value) { +>value : Symbol(value, Decl(emptyAnonymousObjectNarrowing.ts, 64, 13)) + + return 'foo'; + } + if (value === 'xyz') { +>value : Symbol(value, Decl(emptyAnonymousObjectNarrowing.ts, 64, 13)) + + return value; // Type '{}' is not assignable to type 'string'. +>value : Symbol(value, Decl(emptyAnonymousObjectNarrowing.ts, 64, 13)) + } + return ''; +}; + diff --git a/tests/baselines/reference/emptyAnonymousObjectNarrowing(strictnullchecks=true).types b/tests/baselines/reference/emptyAnonymousObjectNarrowing(strictnullchecks=true).types new file mode 100644 index 0000000000000..621db01774a99 --- /dev/null +++ b/tests/baselines/reference/emptyAnonymousObjectNarrowing(strictnullchecks=true).types @@ -0,0 +1,152 @@ +=== tests/cases/compiler/emptyAnonymousObjectNarrowing.ts === +declare let nonNull: {}; +>nonNull : {} + +if (nonNull === "foo") { +>nonNull === "foo" : boolean +>nonNull : {} +>"foo" : "foo" + + nonNull; +>nonNull : "foo" +} +else { + nonNull; +>nonNull : {} +} + +declare let obj: { a: string }; +>obj : { a: string; } +>a : string + +if (nonNull === obj) { +>nonNull === obj : boolean +>nonNull : {} +>obj : { a: string; } + + nonNull; +>nonNull : object +} +else { + nonNull; +>nonNull : {} +} + +function f1(x: T) { +>f1 : (x: T) => void +>x : T + + if (nonNull === x) { +>nonNull === x : boolean +>nonNull : {} +>x : T + + nonNull; +>nonNull : {} + } + else { + nonNull; +>nonNull : {} + } +} + +function f2(x: T) { +>f2 : (x: T) => void +>x : T + + if (nonNull === x) { +>nonNull === x : boolean +>nonNull : {} +>x : T + + nonNull; +>nonNull : {} + } + else { + nonNull; +>nonNull : {} + } +} + +declare let union: "xyz" | { a: string } | undefined; +>union : { a: string; } | "xyz" | undefined +>a : string + +if (nonNull === union) { +>nonNull === union : boolean +>nonNull : {} +>union : { a: string; } | "xyz" | undefined + + nonNull; +>nonNull : {} +} +else { + nonNull; +>nonNull : {} +} + +if (nonNull === undefined) { +>nonNull === undefined : boolean +>nonNull : {} +>undefined : undefined + + nonNull; +>nonNull : never +} +else { + nonNull; +>nonNull : {} +} + +if (nonNull === null) { +>nonNull === null : boolean +>nonNull : {} +>null : null + + nonNull; +>nonNull : never +} +else { + nonNull; +>nonNull : {} +} + +if (nonNull == undefined) { +>nonNull == undefined : boolean +>nonNull : {} +>undefined : undefined + + nonNull; +>nonNull : never +} +else { + nonNull; +>nonNull : {} +} + +// Repro from #50567 +const foo = (value: unknown): string => { +>foo : (value: unknown) => string +>(value: unknown): string => { if (!value) { return 'foo'; } if (value === 'xyz') { return value; // Type '{}' is not assignable to type 'string'. } return '';} : (value: unknown) => string +>value : unknown + + if (!value) { +>!value : boolean +>value : unknown + + return 'foo'; +>'foo' : "foo" + } + if (value === 'xyz') { +>value === 'xyz' : boolean +>value : {} +>'xyz' : "xyz" + + return value; // Type '{}' is not assignable to type 'string'. +>value : "xyz" + } + return ''; +>'' : "" + +}; + diff --git a/tests/cases/compiler/emptyAnonymousObjectNarrowing.ts b/tests/cases/compiler/emptyAnonymousObjectNarrowing.ts new file mode 100644 index 0000000000000..f37c3ee8c47fa --- /dev/null +++ b/tests/cases/compiler/emptyAnonymousObjectNarrowing.ts @@ -0,0 +1,75 @@ +// @strictNullChecks: true,false + +declare let nonNull: {}; +if (nonNull === "foo") { + nonNull; +} +else { + nonNull; +} + +declare let obj: { a: string }; +if (nonNull === obj) { + nonNull; +} +else { + nonNull; +} + +function f1(x: T) { + if (nonNull === x) { + nonNull; + } + else { + nonNull; + } +} + +function f2(x: T) { + if (nonNull === x) { + nonNull; + } + else { + nonNull; + } +} + +declare let union: "xyz" | { a: string } | undefined; +if (nonNull === union) { + nonNull; +} +else { + nonNull; +} + +if (nonNull === undefined) { + nonNull; +} +else { + nonNull; +} + +if (nonNull === null) { + nonNull; +} +else { + nonNull; +} + +if (nonNull == undefined) { + nonNull; +} +else { + nonNull; +} + +// Repro from #50567 +const foo = (value: unknown): string => { + if (!value) { + return 'foo'; + } + if (value === 'xyz') { + return value; // Type '{}' is not assignable to type 'string'. + } + return ''; +};