Skip to content

Commit f3808c4

Browse files
TypeScript BotAndarist
TypeScript Bot
andauthored
🤖 Pick PR #56504 (Fixed an issue in boolean compariso...) into release-5.3 (#56512)
Co-authored-by: Mateusz BurzyÅ„ski <[email protected]>
1 parent b4fe221 commit f3808c4

File tree

5 files changed

+303
-2
lines changed

5 files changed

+303
-2
lines changed

‎src/compiler/checker.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -27886,10 +27886,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2788627886
if (isMatchingConstructorReference(right)) {
2788727887
return narrowTypeByConstructor(type, operator, left, assumeTrue);
2788827888
}
27889-
if (isBooleanLiteral(right)) {
27889+
if (isBooleanLiteral(right) && !isAccessExpression(left)) {
2789027890
return narrowTypeByBooleanComparison(type, left, right, operator, assumeTrue);
2789127891
}
27892-
if (isBooleanLiteral(left)) {
27892+
if (isBooleanLiteral(left) && !isAccessExpression(right)) {
2789327893
return narrowTypeByBooleanComparison(type, right, left, operator, assumeTrue);
2789427894
}
2789527895
break;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
controlFlowOptionalChain3.tsx(30,8): error TS18048: 'foo' is possibly 'undefined'.
2+
controlFlowOptionalChain3.tsx(36,31): error TS18048: 'options' is possibly 'undefined'.
3+
4+
5+
==== controlFlowOptionalChain3.tsx (2 errors) ====
6+
/// <reference path="/.lib/react16.d.ts" />
7+
8+
// https://github.com/microsoft/TypeScript/issues/56482
9+
10+
import React from "react";
11+
12+
interface Foo {
13+
bar: boolean;
14+
}
15+
16+
function test1(foo: Foo | undefined) {
17+
if (foo?.bar === false) {
18+
foo;
19+
}
20+
foo;
21+
}
22+
23+
function test2(foo: Foo | undefined) {
24+
if (foo?.bar === false) {
25+
foo;
26+
} else {
27+
foo;
28+
}
29+
}
30+
31+
function Test3({ foo }: { foo: Foo | undefined }) {
32+
return (
33+
<div>
34+
{foo?.bar === false && "foo"}
35+
{foo.bar ? "true" : "false"}
36+
~~~
37+
!!! error TS18048: 'foo' is possibly 'undefined'.
38+
</div>
39+
);
40+
}
41+
42+
function test4(options?: { a?: boolean; b?: boolean }) {
43+
if (options?.a === false || options.b) {
44+
~~~~~~~
45+
!!! error TS18048: 'options' is possibly 'undefined'.
46+
options;
47+
}
48+
}
49+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
//// [tests/cases/conformance/controlFlow/controlFlowOptionalChain3.tsx] ////
2+
3+
=== controlFlowOptionalChain3.tsx ===
4+
/// <reference path="react16.d.ts" />
5+
6+
// https://github.com/microsoft/TypeScript/issues/56482
7+
8+
import React from "react";
9+
>React : Symbol(React, Decl(controlFlowOptionalChain3.tsx, 4, 6))
10+
11+
interface Foo {
12+
>Foo : Symbol(Foo, Decl(controlFlowOptionalChain3.tsx, 4, 26))
13+
14+
bar: boolean;
15+
>bar : Symbol(Foo.bar, Decl(controlFlowOptionalChain3.tsx, 6, 15))
16+
}
17+
18+
function test1(foo: Foo | undefined) {
19+
>test1 : Symbol(test1, Decl(controlFlowOptionalChain3.tsx, 8, 1))
20+
>foo : Symbol(foo, Decl(controlFlowOptionalChain3.tsx, 10, 15))
21+
>Foo : Symbol(Foo, Decl(controlFlowOptionalChain3.tsx, 4, 26))
22+
23+
if (foo?.bar === false) {
24+
>foo?.bar : Symbol(Foo.bar, Decl(controlFlowOptionalChain3.tsx, 6, 15))
25+
>foo : Symbol(foo, Decl(controlFlowOptionalChain3.tsx, 10, 15))
26+
>bar : Symbol(Foo.bar, Decl(controlFlowOptionalChain3.tsx, 6, 15))
27+
28+
foo;
29+
>foo : Symbol(foo, Decl(controlFlowOptionalChain3.tsx, 10, 15))
30+
}
31+
foo;
32+
>foo : Symbol(foo, Decl(controlFlowOptionalChain3.tsx, 10, 15))
33+
}
34+
35+
function test2(foo: Foo | undefined) {
36+
>test2 : Symbol(test2, Decl(controlFlowOptionalChain3.tsx, 15, 1))
37+
>foo : Symbol(foo, Decl(controlFlowOptionalChain3.tsx, 17, 15))
38+
>Foo : Symbol(Foo, Decl(controlFlowOptionalChain3.tsx, 4, 26))
39+
40+
if (foo?.bar === false) {
41+
>foo?.bar : Symbol(Foo.bar, Decl(controlFlowOptionalChain3.tsx, 6, 15))
42+
>foo : Symbol(foo, Decl(controlFlowOptionalChain3.tsx, 17, 15))
43+
>bar : Symbol(Foo.bar, Decl(controlFlowOptionalChain3.tsx, 6, 15))
44+
45+
foo;
46+
>foo : Symbol(foo, Decl(controlFlowOptionalChain3.tsx, 17, 15))
47+
48+
} else {
49+
foo;
50+
>foo : Symbol(foo, Decl(controlFlowOptionalChain3.tsx, 17, 15))
51+
}
52+
}
53+
54+
function Test3({ foo }: { foo: Foo | undefined }) {
55+
>Test3 : Symbol(Test3, Decl(controlFlowOptionalChain3.tsx, 23, 1))
56+
>foo : Symbol(foo, Decl(controlFlowOptionalChain3.tsx, 25, 16))
57+
>foo : Symbol(foo, Decl(controlFlowOptionalChain3.tsx, 25, 25))
58+
>Foo : Symbol(Foo, Decl(controlFlowOptionalChain3.tsx, 4, 26))
59+
60+
return (
61+
<div>
62+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2546, 114))
63+
64+
{foo?.bar === false && "foo"}
65+
>foo?.bar : Symbol(Foo.bar, Decl(controlFlowOptionalChain3.tsx, 6, 15))
66+
>foo : Symbol(foo, Decl(controlFlowOptionalChain3.tsx, 25, 16))
67+
>bar : Symbol(Foo.bar, Decl(controlFlowOptionalChain3.tsx, 6, 15))
68+
69+
{foo.bar ? "true" : "false"}
70+
>foo.bar : Symbol(Foo.bar, Decl(controlFlowOptionalChain3.tsx, 6, 15))
71+
>foo : Symbol(foo, Decl(controlFlowOptionalChain3.tsx, 25, 16))
72+
>bar : Symbol(Foo.bar, Decl(controlFlowOptionalChain3.tsx, 6, 15))
73+
74+
</div>
75+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2546, 114))
76+
77+
);
78+
}
79+
80+
function test4(options?: { a?: boolean; b?: boolean }) {
81+
>test4 : Symbol(test4, Decl(controlFlowOptionalChain3.tsx, 32, 1))
82+
>options : Symbol(options, Decl(controlFlowOptionalChain3.tsx, 34, 15))
83+
>a : Symbol(a, Decl(controlFlowOptionalChain3.tsx, 34, 26))
84+
>b : Symbol(b, Decl(controlFlowOptionalChain3.tsx, 34, 39))
85+
86+
if (options?.a === false || options.b) {
87+
>options?.a : Symbol(a, Decl(controlFlowOptionalChain3.tsx, 34, 26))
88+
>options : Symbol(options, Decl(controlFlowOptionalChain3.tsx, 34, 15))
89+
>a : Symbol(a, Decl(controlFlowOptionalChain3.tsx, 34, 26))
90+
>options.b : Symbol(b, Decl(controlFlowOptionalChain3.tsx, 34, 39))
91+
>options : Symbol(options, Decl(controlFlowOptionalChain3.tsx, 34, 15))
92+
>b : Symbol(b, Decl(controlFlowOptionalChain3.tsx, 34, 39))
93+
94+
options;
95+
>options : Symbol(options, Decl(controlFlowOptionalChain3.tsx, 34, 15))
96+
}
97+
}
98+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
//// [tests/cases/conformance/controlFlow/controlFlowOptionalChain3.tsx] ////
2+
3+
=== controlFlowOptionalChain3.tsx ===
4+
/// <reference path="react16.d.ts" />
5+
6+
// https://github.com/microsoft/TypeScript/issues/56482
7+
8+
import React from "react";
9+
>React : typeof React
10+
11+
interface Foo {
12+
bar: boolean;
13+
>bar : boolean
14+
}
15+
16+
function test1(foo: Foo | undefined) {
17+
>test1 : (foo: Foo | undefined) => void
18+
>foo : Foo | undefined
19+
20+
if (foo?.bar === false) {
21+
>foo?.bar === false : boolean
22+
>foo?.bar : boolean | undefined
23+
>foo : Foo | undefined
24+
>bar : boolean | undefined
25+
>false : false
26+
27+
foo;
28+
>foo : Foo
29+
}
30+
foo;
31+
>foo : Foo | undefined
32+
}
33+
34+
function test2(foo: Foo | undefined) {
35+
>test2 : (foo: Foo | undefined) => void
36+
>foo : Foo | undefined
37+
38+
if (foo?.bar === false) {
39+
>foo?.bar === false : boolean
40+
>foo?.bar : boolean | undefined
41+
>foo : Foo | undefined
42+
>bar : boolean | undefined
43+
>false : false
44+
45+
foo;
46+
>foo : Foo
47+
48+
} else {
49+
foo;
50+
>foo : Foo | undefined
51+
}
52+
}
53+
54+
function Test3({ foo }: { foo: Foo | undefined }) {
55+
>Test3 : ({ foo }: { foo: Foo | undefined; }) => JSX.Element
56+
>foo : Foo | undefined
57+
>foo : Foo | undefined
58+
59+
return (
60+
>( <div> {foo?.bar === false && "foo"} {foo.bar ? "true" : "false"} </div> ) : JSX.Element
61+
62+
<div>
63+
><div> {foo?.bar === false && "foo"} {foo.bar ? "true" : "false"} </div> : JSX.Element
64+
>div : any
65+
66+
{foo?.bar === false && "foo"}
67+
>foo?.bar === false && "foo" : false | "foo"
68+
>foo?.bar === false : boolean
69+
>foo?.bar : boolean | undefined
70+
>foo : Foo | undefined
71+
>bar : boolean | undefined
72+
>false : false
73+
>"foo" : "foo"
74+
75+
{foo.bar ? "true" : "false"}
76+
>foo.bar ? "true" : "false" : "false" | "true"
77+
>foo.bar : boolean
78+
>foo : Foo | undefined
79+
>bar : boolean
80+
>"true" : "true"
81+
>"false" : "false"
82+
83+
</div>
84+
>div : any
85+
86+
);
87+
}
88+
89+
function test4(options?: { a?: boolean; b?: boolean }) {
90+
>test4 : (options?: { a?: boolean; b?: boolean;}) => void
91+
>options : { a?: boolean | undefined; b?: boolean | undefined; } | undefined
92+
>a : boolean | undefined
93+
>b : boolean | undefined
94+
95+
if (options?.a === false || options.b) {
96+
>options?.a === false || options.b : boolean | undefined
97+
>options?.a === false : boolean
98+
>options?.a : boolean | undefined
99+
>options : { a?: boolean | undefined; b?: boolean | undefined; } | undefined
100+
>a : boolean | undefined
101+
>false : false
102+
>options.b : boolean | undefined
103+
>options : { a?: boolean | undefined; b?: boolean | undefined; } | undefined
104+
>b : boolean | undefined
105+
106+
options;
107+
>options : { a?: boolean | undefined; b?: boolean | undefined; } | undefined
108+
}
109+
}
110+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// @strict: true
2+
// @noEmit: true
3+
// @esModuleInterop: true
4+
// @jsx: react
5+
6+
/// <reference path="/.lib/react16.d.ts" />
7+
8+
// https://github.com/microsoft/TypeScript/issues/56482
9+
10+
import React from "react";
11+
12+
interface Foo {
13+
bar: boolean;
14+
}
15+
16+
function test1(foo: Foo | undefined) {
17+
if (foo?.bar === false) {
18+
foo;
19+
}
20+
foo;
21+
}
22+
23+
function test2(foo: Foo | undefined) {
24+
if (foo?.bar === false) {
25+
foo;
26+
} else {
27+
foo;
28+
}
29+
}
30+
31+
function Test3({ foo }: { foo: Foo | undefined }) {
32+
return (
33+
<div>
34+
{foo?.bar === false && "foo"}
35+
{foo.bar ? "true" : "false"}
36+
</div>
37+
);
38+
}
39+
40+
function test4(options?: { a?: boolean; b?: boolean }) {
41+
if (options?.a === false || options.b) {
42+
options;
43+
}
44+
}

0 commit comments

Comments
 (0)