TypeScript/tests/baselines/reference/exhaustiveSwitchStatements1.types
Titian Cernicova-Dragomir 71661b932a
Fixed issue where non null assertion caused getFlowTypeOfReference to return the declared type if the type was already narrowed to never. (#35863)
This was caused by the fact that getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull) will return never both if resultType was already never and if resultType does not contain undefined or null. In the latter case returning the declaring type is correct, in the former case this causes something narrowed to never to still be typed as the original declared type.
2021-03-11 07:33:33 -08:00

736 lines
14 KiB
Plaintext

=== tests/cases/conformance/controlFlow/exhaustiveSwitchStatements1.ts ===
function f1(x: 1 | 2): string {
>f1 : (x: 1 | 2) => string
>x : 1 | 2
if (!!true) {
>!!true : true
>!true : false
>true : true
switch (x) {
>x : 1 | 2
case 1: return 'a';
>1 : 1
>'a' : "a"
case 2: return 'b';
>2 : 2
>'b' : "b"
}
x; // Unreachable
>x : never
}
else {
throw 0;
>0 : 0
}
}
function f2(x: 1 | 2) {
>f2 : (x: 1 | 2) => void
>x : 1 | 2
let z: number;
>z : number
switch (x) {
>x : 1 | 2
case 1: z = 10; break;
>1 : 1
>z = 10 : 10
>z : number
>10 : 10
case 2: z = 20; break;
>2 : 2
>z = 20 : 20
>z : number
>20 : 20
}
z; // Definitely assigned
>z : number
}
function f3(x: 1 | 2) {
>f3 : (x: 1 | 2) => 10 | 20
>x : 1 | 2
switch (x) {
>x : 1 | 2
case 1: return 10;
>1 : 1
>10 : 10
case 2: return 20;
>2 : 2
>20 : 20
// Default considered reachable to allow defensive coding
default: throw new Error("Bad input");
>new Error("Bad input") : Error
>Error : ErrorConstructor
>"Bad input" : "Bad input"
}
}
// Repro from #11572
enum E { A, B }
>E : E
>A : E.A
>B : E.B
function f(e: E): number {
>f : (e: E) => number
>e : E
switch (e) {
>e : E
case E.A: return 0
>E.A : E.A
>E : typeof E
>A : E.A
>0 : 0
case E.B: return 1
>E.B : E.B
>E : typeof E
>B : E.B
>1 : 1
}
}
function g(e: E): number {
>g : (e: E) => number
>e : E
if (!true)
>!true : false
>true : true
return -1
>-1 : -1
>1 : 1
else
switch (e) {
>e : E
case E.A: return 0
>E.A : E.A
>E : typeof E
>A : E.A
>0 : 0
case E.B: return 1
>E.B : E.B
>E : typeof E
>B : E.B
>1 : 1
}
}
// Repro from #12668
interface Square { kind: "square"; size: number; }
>kind : "square"
>size : number
interface Rectangle { kind: "rectangle"; width: number; height: number; }
>kind : "rectangle"
>width : number
>height : number
interface Circle { kind: "circle"; radius: number; }
>kind : "circle"
>radius : number
interface Triangle { kind: "triangle"; side: number; }
>kind : "triangle"
>side : number
type Shape = Square | Rectangle | Circle | Triangle;
>Shape : Shape
function area(s: Shape): number {
>area : (s: Shape) => number
>s : Shape
let area;
>area : any
switch (s.kind) {
>s.kind : "square" | "rectangle" | "circle" | "triangle"
>s : Shape
>kind : "square" | "rectangle" | "circle" | "triangle"
case "square": area = s.size * s.size; break;
>"square" : "square"
>area = s.size * s.size : number
>area : any
>s.size * s.size : number
>s.size : number
>s : Square
>size : number
>s.size : number
>s : Square
>size : number
case "rectangle": area = s.width * s.height; break;
>"rectangle" : "rectangle"
>area = s.width * s.height : number
>area : any
>s.width * s.height : number
>s.width : number
>s : Rectangle
>width : number
>s.height : number
>s : Rectangle
>height : number
case "circle": area = Math.PI * s.radius * s.radius; break;
>"circle" : "circle"
>area = Math.PI * s.radius * s.radius : number
>area : any
>Math.PI * s.radius * s.radius : number
>Math.PI * s.radius : number
>Math.PI : number
>Math : Math
>PI : number
>s.radius : number
>s : Circle
>radius : number
>s.radius : number
>s : Circle
>radius : number
case "triangle": area = Math.sqrt(3) / 4 * s.side * s.side; break;
>"triangle" : "triangle"
>area = Math.sqrt(3) / 4 * s.side * s.side : number
>area : any
>Math.sqrt(3) / 4 * s.side * s.side : number
>Math.sqrt(3) / 4 * s.side : number
>Math.sqrt(3) / 4 : number
>Math.sqrt(3) : number
>Math.sqrt : (x: number) => number
>Math : Math
>sqrt : (x: number) => number
>3 : 3
>4 : 4
>s.side : number
>s : Triangle
>side : number
>s.side : number
>s : Triangle
>side : number
}
return area;
>area : number
}
function areaWrapped(s: Shape): number {
>areaWrapped : (s: Shape) => number
>s : Shape
let area;
>area : any
area = (() => {
>area = (() => { switch (s.kind) { case "square": return s.size * s.size; case "rectangle": return s.width * s.height; case "circle": return Math.PI * s.radius * s.radius; case "triangle": return Math.sqrt(3) / 4 * s.side * s.side; } })() : number
>area : any
>(() => { switch (s.kind) { case "square": return s.size * s.size; case "rectangle": return s.width * s.height; case "circle": return Math.PI * s.radius * s.radius; case "triangle": return Math.sqrt(3) / 4 * s.side * s.side; } })() : number
>(() => { switch (s.kind) { case "square": return s.size * s.size; case "rectangle": return s.width * s.height; case "circle": return Math.PI * s.radius * s.radius; case "triangle": return Math.sqrt(3) / 4 * s.side * s.side; } }) : () => number
>() => { switch (s.kind) { case "square": return s.size * s.size; case "rectangle": return s.width * s.height; case "circle": return Math.PI * s.radius * s.radius; case "triangle": return Math.sqrt(3) / 4 * s.side * s.side; } } : () => number
switch (s.kind) {
>s.kind : "square" | "rectangle" | "circle" | "triangle"
>s : Shape
>kind : "square" | "rectangle" | "circle" | "triangle"
case "square": return s.size * s.size;
>"square" : "square"
>s.size * s.size : number
>s.size : number
>s : Square
>size : number
>s.size : number
>s : Square
>size : number
case "rectangle": return s.width * s.height;
>"rectangle" : "rectangle"
>s.width * s.height : number
>s.width : number
>s : Rectangle
>width : number
>s.height : number
>s : Rectangle
>height : number
case "circle": return Math.PI * s.radius * s.radius;
>"circle" : "circle"
>Math.PI * s.radius * s.radius : number
>Math.PI * s.radius : number
>Math.PI : number
>Math : Math
>PI : number
>s.radius : number
>s : Circle
>radius : number
>s.radius : number
>s : Circle
>radius : number
case "triangle": return Math.sqrt(3) / 4 * s.side * s.side;
>"triangle" : "triangle"
>Math.sqrt(3) / 4 * s.side * s.side : number
>Math.sqrt(3) / 4 * s.side : number
>Math.sqrt(3) / 4 : number
>Math.sqrt(3) : number
>Math.sqrt : (x: number) => number
>Math : Math
>sqrt : (x: number) => number
>3 : 3
>4 : 4
>s.side : number
>s : Triangle
>side : number
>s.side : number
>s : Triangle
>side : number
}
})();
return area;
>area : number
}
// Repro from #13241
enum MyEnum {
>MyEnum : MyEnum
A,
>A : MyEnum.A
B
>B : MyEnum.B
}
function thisGivesError(e: MyEnum): string {
>thisGivesError : (e: MyEnum) => string
>e : MyEnum
let s: string;
>s : string
switch (e) {
>e : MyEnum
case MyEnum.A: s = "it was A"; break;
>MyEnum.A : MyEnum.A
>MyEnum : typeof MyEnum
>A : MyEnum.A
>s = "it was A" : "it was A"
>s : string
>"it was A" : "it was A"
case MyEnum.B: s = "it was B"; break;
>MyEnum.B : MyEnum.B
>MyEnum : typeof MyEnum
>B : MyEnum.B
>s = "it was B" : "it was B"
>s : string
>"it was B" : "it was B"
}
return s;
>s : string
}
function good1(e: MyEnum): string {
>good1 : (e: MyEnum) => string
>e : MyEnum
let s: string;
>s : string
switch (e) {
>e : MyEnum
case MyEnum.A: s = "it was A"; break;
>MyEnum.A : MyEnum.A
>MyEnum : typeof MyEnum
>A : MyEnum.A
>s = "it was A" : "it was A"
>s : string
>"it was A" : "it was A"
case MyEnum.B: s = "it was B"; break;
>MyEnum.B : MyEnum.B
>MyEnum : typeof MyEnum
>B : MyEnum.B
>s = "it was B" : "it was B"
>s : string
>"it was B" : "it was B"
default: s = "it was something else"; break;
>s = "it was something else" : "it was something else"
>s : string
>"it was something else" : "it was something else"
}
return s;
>s : string
}
function good2(e: MyEnum): string {
>good2 : (e: MyEnum) => string
>e : MyEnum
switch (e) {
>e : MyEnum
case MyEnum.A: return "it was A";
>MyEnum.A : MyEnum.A
>MyEnum : typeof MyEnum
>A : MyEnum.A
>"it was A" : "it was A"
case MyEnum.B: return "it was B";
>MyEnum.B : MyEnum.B
>MyEnum : typeof MyEnum
>B : MyEnum.B
>"it was B" : "it was B"
}
}
// Repro from #18362
enum Level {
>Level : Level
One,
>One : Level.One
Two,
>Two : Level.Two
}
const doSomethingWithLevel = (level: Level) => {
>doSomethingWithLevel : (level: Level) => Level
>(level: Level) => { let next: Level; switch (level) { case Level.One: next = Level.Two; break; case Level.Two: next = Level.One; break; } return next;} : (level: Level) => Level
>level : Level
let next: Level;
>next : Level
switch (level) {
>level : Level
case Level.One:
>Level.One : Level.One
>Level : typeof Level
>One : Level.One
next = Level.Two;
>next = Level.Two : Level.Two
>next : Level
>Level.Two : Level.Two
>Level : typeof Level
>Two : Level.Two
break;
case Level.Two:
>Level.Two : Level.Two
>Level : typeof Level
>Two : Level.Two
next = Level.One;
>next = Level.One : Level.One
>next : Level
>Level.One : Level.One
>Level : typeof Level
>One : Level.One
break;
}
return next;
>next : Level
};
// Repro from #20409
interface Square2 {
kind: "square";
>kind : "square"
size: number;
>size : number
}
interface Circle2 {
kind: "circle";
>kind : "circle"
radius: number;
>radius : number
}
type Shape2 = Square2 | Circle2;
>Shape2 : Shape2
function withDefault(s1: Shape2, s2: Shape2): string {
>withDefault : (s1: Shape2, s2: Shape2) => string
>s1 : Shape2
>s2 : Shape2
switch (s1.kind) {
>s1.kind : "square" | "circle"
>s1 : Shape2
>kind : "square" | "circle"
case "square":
>"square" : "square"
return "1";
>"1" : "1"
case "circle":
>"circle" : "circle"
switch (s2.kind) {
>s2.kind : "square" | "circle"
>s2 : Shape2
>kind : "square" | "circle"
case "square":
>"square" : "square"
return "2";
>"2" : "2"
case "circle":
>"circle" : "circle"
return "3";
>"3" : "3"
default:
return "never";
>"never" : "never"
}
}
}
function withoutDefault(s1: Shape2, s2: Shape2): string {
>withoutDefault : (s1: Shape2, s2: Shape2) => string
>s1 : Shape2
>s2 : Shape2
switch (s1.kind) {
>s1.kind : "square" | "circle"
>s1 : Shape2
>kind : "square" | "circle"
case "square":
>"square" : "square"
return "1";
>"1" : "1"
case "circle":
>"circle" : "circle"
switch (s2.kind) {
>s2.kind : "square" | "circle"
>s2 : Shape2
>kind : "square" | "circle"
case "square":
>"square" : "square"
return "2";
>"2" : "2"
case "circle":
>"circle" : "circle"
return "3";
>"3" : "3"
}
}
}
// Repro from #20823
function test4(value: 1 | 2) {
>test4 : (value: 1 | 2) => string
>value : 1 | 2
let x: string;
>x : string
switch (value) {
>value : 1 | 2
case 1: x = "one"; break;
>1 : 1
>x = "one" : "one"
>x : string
>"one" : "one"
case 2: x = "two"; break;
>2 : 2
>x = "two" : "two"
>x : string
>"two" : "two"
}
return x;
>x : string
}
// Repro from #34661
enum Animal { DOG, CAT }
>Animal : Animal
>DOG : Animal.DOG
>CAT : Animal.CAT
declare const zoo: { animal: Animal } | undefined;
>zoo : { animal: Animal; } | undefined
>animal : Animal
function expression(): Animal {
>expression : () => Animal
switch (zoo?.animal ?? Animal.DOG) {
>zoo?.animal ?? Animal.DOG : Animal
>zoo?.animal : Animal | undefined
>zoo : { animal: Animal; } | undefined
>animal : Animal | undefined
>Animal.DOG : Animal.DOG
>Animal : typeof Animal
>DOG : Animal.DOG
case Animal.DOG: return Animal.DOG
>Animal.DOG : Animal.DOG
>Animal : typeof Animal
>DOG : Animal.DOG
>Animal.DOG : Animal.DOG
>Animal : typeof Animal
>DOG : Animal.DOG
case Animal.CAT: return Animal.CAT
>Animal.CAT : Animal.CAT
>Animal : typeof Animal
>CAT : Animal.CAT
>Animal.CAT : Animal.CAT
>Animal : typeof Animal
>CAT : Animal.CAT
}
}
// Repro from #34840
function foo() {
>foo : () => void
const foo: number | undefined = 0;
>foo : number | undefined
>0 : 0
while (true) {
>true : true
const stats = foo;
>stats : number
>foo : number
switch (stats) {
>stats : number
case 1: break;
>1 : 1
case 2: break;
>2 : 2
}
}
}
// Repro from #35070
type O = {
>O : O
a: number,
>a : number
b: number
>b : number
};
type K = keyof O | 'c';
>K : K
function ff(o: O, k: K) {
>ff : (o: O, k: K) => number
>o : O
>k : K
switch(k) {
>k : K
case 'c':
>'c' : "c"
k = 'a';
>k = 'a' : "a"
>k : K
>'a' : "a"
}
k === 'c'; // Error
>k === 'c' : boolean
>k : keyof O
>'c' : "c"
return o[k];
>o[k] : number
>o : O
>k : keyof O
}
// Repro from #35431
type A = { kind: "abc" } | { kind: "def" };
>A : A
>kind : "abc"
>kind : "def"
function f35431(a: A) {
>f35431 : (a: A) => void
>a : A
switch (a.kind) {
>a.kind : "abc" | "def"
>a : A
>kind : "abc" | "def"
case "abc":
>"abc" : "abc"
case "def": return;
>"def" : "def"
default:
a!.kind; // Error expected
>a!.kind : any
>a! : never
>a : never
>kind : any
}
}