Skip to content

Commit 3bd063d

Browse files
committed
fix control flow in switch case
1 parent 4d5d1b3 commit 3bd063d

File tree

5 files changed

+166
-0
lines changed

5 files changed

+166
-0
lines changed

src/compiler/checker.ts

+4
Original file line numberDiff line numberDiff line change
@@ -19324,6 +19324,10 @@ namespace ts {
1932419324
if (propName === undefined) {
1932519325
return type;
1932619326
}
19327+
if (strictNullChecks && access.questionDotToken) {
19328+
type = getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull)
19329+
}
19330+
1932719331
const propType = getTypeOfPropertyOfType(type, propName);
1932819332
const narrowedPropType = propType && narrowType(propType);
1932919333
return propType === narrowedPropType ? type : filterType(type, t => isTypeComparableTo(getTypeOfPropertyOrIndexSignature(t, propName), narrowedPropType!));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//// [controlFlowOptionalChain1.ts]
2+
type Shape =
3+
| { type: 'rectangle', width: number, height: number }
4+
| { type: 'circle', radius: number }
5+
6+
declare function assertUndefined(v: undefined): void
7+
8+
function getArea(shape?: Shape) {
9+
switch (shape?.type) {
10+
case 'circle':
11+
return Math.PI * shape.radius ** 2
12+
case 'rectangle':
13+
return shape.width * shape.height
14+
default:
15+
return assertUndefined(shape)
16+
}
17+
}
18+
19+
20+
//// [controlFlowOptionalChain1.js]
21+
"use strict";
22+
function getArea(shape) {
23+
var _a;
24+
switch ((_a = shape) === null || _a === void 0 ? void 0 : _a.type) {
25+
case 'circle':
26+
return Math.PI * Math.pow(shape.radius, 2);
27+
case 'rectangle':
28+
return shape.width * shape.height;
29+
default:
30+
return assertUndefined(shape);
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
=== tests/cases/conformance/controlFlow/controlFlowOptionalChain1.ts ===
2+
type Shape =
3+
>Shape : Symbol(Shape, Decl(controlFlowOptionalChain1.ts, 0, 0))
4+
5+
| { type: 'rectangle', width: number, height: number }
6+
>type : Symbol(type, Decl(controlFlowOptionalChain1.ts, 1, 7))
7+
>width : Symbol(width, Decl(controlFlowOptionalChain1.ts, 1, 26))
8+
>height : Symbol(height, Decl(controlFlowOptionalChain1.ts, 1, 41))
9+
10+
| { type: 'circle', radius: number }
11+
>type : Symbol(type, Decl(controlFlowOptionalChain1.ts, 2, 7))
12+
>radius : Symbol(radius, Decl(controlFlowOptionalChain1.ts, 2, 23))
13+
14+
declare function assertUndefined(v: undefined): void
15+
>assertUndefined : Symbol(assertUndefined, Decl(controlFlowOptionalChain1.ts, 2, 40))
16+
>v : Symbol(v, Decl(controlFlowOptionalChain1.ts, 4, 33))
17+
18+
function getArea(shape?: Shape) {
19+
>getArea : Symbol(getArea, Decl(controlFlowOptionalChain1.ts, 4, 52))
20+
>shape : Symbol(shape, Decl(controlFlowOptionalChain1.ts, 6, 17))
21+
>Shape : Symbol(Shape, Decl(controlFlowOptionalChain1.ts, 0, 0))
22+
23+
switch (shape?.type) {
24+
>shape?.type : Symbol(type, Decl(controlFlowOptionalChain1.ts, 1, 7), Decl(controlFlowOptionalChain1.ts, 2, 7))
25+
>shape : Symbol(shape, Decl(controlFlowOptionalChain1.ts, 6, 17))
26+
>type : Symbol(type, Decl(controlFlowOptionalChain1.ts, 1, 7), Decl(controlFlowOptionalChain1.ts, 2, 7))
27+
28+
case 'circle':
29+
return Math.PI * shape.radius ** 2
30+
>Math.PI : Symbol(Math.PI, Decl(lib.es5.d.ts, --, --))
31+
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
32+
>PI : Symbol(Math.PI, Decl(lib.es5.d.ts, --, --))
33+
>shape.radius : Symbol(radius, Decl(controlFlowOptionalChain1.ts, 2, 23))
34+
>shape : Symbol(shape, Decl(controlFlowOptionalChain1.ts, 6, 17))
35+
>radius : Symbol(radius, Decl(controlFlowOptionalChain1.ts, 2, 23))
36+
37+
case 'rectangle':
38+
return shape.width * shape.height
39+
>shape.width : Symbol(width, Decl(controlFlowOptionalChain1.ts, 1, 26))
40+
>shape : Symbol(shape, Decl(controlFlowOptionalChain1.ts, 6, 17))
41+
>width : Symbol(width, Decl(controlFlowOptionalChain1.ts, 1, 26))
42+
>shape.height : Symbol(height, Decl(controlFlowOptionalChain1.ts, 1, 41))
43+
>shape : Symbol(shape, Decl(controlFlowOptionalChain1.ts, 6, 17))
44+
>height : Symbol(height, Decl(controlFlowOptionalChain1.ts, 1, 41))
45+
46+
default:
47+
return assertUndefined(shape)
48+
>assertUndefined : Symbol(assertUndefined, Decl(controlFlowOptionalChain1.ts, 2, 40))
49+
>shape : Symbol(shape, Decl(controlFlowOptionalChain1.ts, 6, 17))
50+
}
51+
}
52+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
=== tests/cases/conformance/controlFlow/controlFlowOptionalChain1.ts ===
2+
type Shape =
3+
>Shape : Shape
4+
5+
| { type: 'rectangle', width: number, height: number }
6+
>type : "rectangle"
7+
>width : number
8+
>height : number
9+
10+
| { type: 'circle', radius: number }
11+
>type : "circle"
12+
>radius : number
13+
14+
declare function assertUndefined(v: undefined): void
15+
>assertUndefined : (v: undefined) => void
16+
>v : undefined
17+
18+
function getArea(shape?: Shape) {
19+
>getArea : (shape?: { type: "rectangle"; width: number; height: number; } | { type: "circle"; radius: number; } | undefined) => number | void
20+
>shape : { type: "rectangle"; width: number; height: number; } | { type: "circle"; radius: number; } | undefined
21+
22+
switch (shape?.type) {
23+
>shape?.type : "rectangle" | "circle" | undefined
24+
>shape : { type: "rectangle"; width: number; height: number; } | { type: "circle"; radius: number; } | undefined
25+
>type : "rectangle" | "circle" | undefined
26+
27+
case 'circle':
28+
>'circle' : "circle"
29+
30+
return Math.PI * shape.radius ** 2
31+
>Math.PI * shape.radius ** 2 : number
32+
>Math.PI : number
33+
>Math : Math
34+
>PI : number
35+
>shape.radius ** 2 : number
36+
>shape.radius : number
37+
>shape : { type: "circle"; radius: number; }
38+
>radius : number
39+
>2 : 2
40+
41+
case 'rectangle':
42+
>'rectangle' : "rectangle"
43+
44+
return shape.width * shape.height
45+
>shape.width * shape.height : number
46+
>shape.width : number
47+
>shape : { type: "rectangle"; width: number; height: number; }
48+
>width : number
49+
>shape.height : number
50+
>shape : { type: "rectangle"; width: number; height: number; }
51+
>height : number
52+
53+
default:
54+
return assertUndefined(shape)
55+
>assertUndefined(shape) : void
56+
>assertUndefined : (v: undefined) => void
57+
>shape : never
58+
}
59+
}
60+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// @strict: true
2+
3+
type Shape =
4+
| { type: 'rectangle', width: number, height: number }
5+
| { type: 'circle', radius: number }
6+
7+
declare function assertUndefined(v: undefined): void
8+
9+
function getArea(shape?: Shape) {
10+
switch (shape?.type) {
11+
case 'circle':
12+
return Math.PI * shape.radius ** 2
13+
case 'rectangle':
14+
return shape.width * shape.height
15+
default:
16+
return assertUndefined(shape)
17+
}
18+
}

0 commit comments

Comments
 (0)