Properly analyze switch statement bypass control flow (#35087)
* Properly analyze switch statement bypass control flow * Add regression test * Accept new baselines
This commit is contained in:
parent
aa39080ac7
commit
38db7ae59e
|
@ -19333,7 +19333,7 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
if (bypassFlow) {
|
||||
const flowType = getTypeAtFlowNode(bypassFlow.antecedent);
|
||||
const flowType = getTypeAtFlowNode(bypassFlow);
|
||||
const type = getTypeFromFlowType(flowType);
|
||||
// If the bypass flow contributes a type we haven't seen yet and the switch statement
|
||||
// isn't exhaustive, process the bypass flow type. Since exhaustiveness checks increase
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
tests/cases/conformance/controlFlow/exhaustiveSwitchStatements1.ts(7,9): error TS7027: Unreachable code detected.
|
||||
tests/cases/conformance/controlFlow/exhaustiveSwitchStatements1.ts(235,5): error TS2367: This condition will always return 'false' since the types '"a" | "b"' and '"c"' have no overlap.
|
||||
|
||||
|
||||
==== tests/cases/conformance/controlFlow/exhaustiveSwitchStatements1.ts (1 errors) ====
|
||||
==== tests/cases/conformance/controlFlow/exhaustiveSwitchStatements1.ts (2 errors) ====
|
||||
function f1(x: 1 | 2): string {
|
||||
if (!!true) {
|
||||
switch (x) {
|
||||
|
@ -225,4 +226,22 @@ tests/cases/conformance/controlFlow/exhaustiveSwitchStatements1.ts(7,9): error T
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #35070
|
||||
|
||||
type O = {
|
||||
a: number,
|
||||
b: number
|
||||
};
|
||||
type K = keyof O | 'c';
|
||||
function ff(o: O, k: K) {
|
||||
switch(k) {
|
||||
case 'c':
|
||||
k = 'a';
|
||||
}
|
||||
k === 'c'; // Error
|
||||
~~~~~~~~~
|
||||
!!! error TS2367: This condition will always return 'false' since the types '"a" | "b"' and '"c"' have no overlap.
|
||||
return o[k];
|
||||
}
|
||||
|
|
@ -220,6 +220,22 @@ function foo() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #35070
|
||||
|
||||
type O = {
|
||||
a: number,
|
||||
b: number
|
||||
};
|
||||
type K = keyof O | 'c';
|
||||
function ff(o: O, k: K) {
|
||||
switch(k) {
|
||||
case 'c':
|
||||
k = 'a';
|
||||
}
|
||||
k === 'c'; // Error
|
||||
return o[k];
|
||||
}
|
||||
|
||||
|
||||
//// [exhaustiveSwitchStatements1.js]
|
||||
|
@ -429,6 +445,14 @@ function foo() {
|
|||
}
|
||||
}
|
||||
}
|
||||
function ff(o, k) {
|
||||
switch (k) {
|
||||
case 'c':
|
||||
k = 'a';
|
||||
}
|
||||
k === 'c'; // Error
|
||||
return o[k];
|
||||
}
|
||||
|
||||
|
||||
//// [exhaustiveSwitchStatements1.d.ts]
|
||||
|
@ -494,3 +518,9 @@ declare const zoo: {
|
|||
} | undefined;
|
||||
declare function expression(): Animal;
|
||||
declare function foo(): void;
|
||||
declare type O = {
|
||||
a: number;
|
||||
b: number;
|
||||
};
|
||||
declare type K = keyof O | 'c';
|
||||
declare function ff(o: O, k: K): number;
|
||||
|
|
|
@ -565,3 +565,41 @@ function foo() {
|
|||
}
|
||||
}
|
||||
|
||||
// Repro from #35070
|
||||
|
||||
type O = {
|
||||
>O : Symbol(O, Decl(exhaustiveSwitchStatements1.ts, 220, 1))
|
||||
|
||||
a: number,
|
||||
>a : Symbol(a, Decl(exhaustiveSwitchStatements1.ts, 224, 10))
|
||||
|
||||
b: number
|
||||
>b : Symbol(b, Decl(exhaustiveSwitchStatements1.ts, 225, 14))
|
||||
|
||||
};
|
||||
type K = keyof O | 'c';
|
||||
>K : Symbol(K, Decl(exhaustiveSwitchStatements1.ts, 227, 2))
|
||||
>O : Symbol(O, Decl(exhaustiveSwitchStatements1.ts, 220, 1))
|
||||
|
||||
function ff(o: O, k: K) {
|
||||
>ff : Symbol(ff, Decl(exhaustiveSwitchStatements1.ts, 228, 23))
|
||||
>o : Symbol(o, Decl(exhaustiveSwitchStatements1.ts, 229, 12))
|
||||
>O : Symbol(O, Decl(exhaustiveSwitchStatements1.ts, 220, 1))
|
||||
>k : Symbol(k, Decl(exhaustiveSwitchStatements1.ts, 229, 17))
|
||||
>K : Symbol(K, Decl(exhaustiveSwitchStatements1.ts, 227, 2))
|
||||
|
||||
switch(k) {
|
||||
>k : Symbol(k, Decl(exhaustiveSwitchStatements1.ts, 229, 17))
|
||||
|
||||
case 'c':
|
||||
k = 'a';
|
||||
>k : Symbol(k, Decl(exhaustiveSwitchStatements1.ts, 229, 17))
|
||||
}
|
||||
k === 'c'; // Error
|
||||
>k : Symbol(k, Decl(exhaustiveSwitchStatements1.ts, 229, 17))
|
||||
|
||||
return o[k];
|
||||
>o : Symbol(o, Decl(exhaustiveSwitchStatements1.ts, 229, 12))
|
||||
>k : Symbol(k, Decl(exhaustiveSwitchStatements1.ts, 229, 17))
|
||||
}
|
||||
|
||||
|
|
|
@ -662,3 +662,45 @@ function foo() {
|
|||
}
|
||||
}
|
||||
|
||||
// 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 : "a" | "b"
|
||||
>'c' : "c"
|
||||
|
||||
return o[k];
|
||||
>o[k] : number
|
||||
>o : O
|
||||
>k : "a" | "b"
|
||||
}
|
||||
|
||||
|
|
|
@ -223,3 +223,19 @@ function foo() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #35070
|
||||
|
||||
type O = {
|
||||
a: number,
|
||||
b: number
|
||||
};
|
||||
type K = keyof O | 'c';
|
||||
function ff(o: O, k: K) {
|
||||
switch(k) {
|
||||
case 'c':
|
||||
k = 'a';
|
||||
}
|
||||
k === 'c'; // Error
|
||||
return o[k];
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue