mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 11:35:42 -06:00
Merge pull request #27612 from Microsoft/fixSwitchCaseControlFlow
Fix switch case control flow
This commit is contained in:
commit
6a9055ca0b
@ -1181,7 +1181,6 @@ namespace ts {
|
||||
}
|
||||
const preCaseLabel = createBranchLabel();
|
||||
addAntecedent(preCaseLabel, createFlowSwitchClause(preSwitchCaseFlow!, node.parent, clauseStart, i + 1));
|
||||
addAntecedent(preCaseLabel, createFlowSwitchClause(preSwitchCaseFlow!, node.parent, clauseStart, i + 1));
|
||||
addAntecedent(preCaseLabel, fallthroughFlow);
|
||||
currentFlow = finishFlowLabel(preCaseLabel);
|
||||
const clause = clauses[i];
|
||||
|
||||
@ -14972,9 +14972,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getTypeAtSwitchClause(flow: FlowSwitchClause): FlowType {
|
||||
const expr = flow.switchStatement.expression;
|
||||
if (containsMatchingReferenceDiscriminant(reference, expr)) {
|
||||
return declaredType;
|
||||
}
|
||||
const flowType = getTypeAtFlowNode(flow.antecedent);
|
||||
let type = getTypeFromFlowType(flowType);
|
||||
const expr = flow.switchStatement.expression;
|
||||
if (isMatchingReference(reference, expr)) {
|
||||
type = narrowTypeBySwitchOnDiscriminant(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
|
||||
}
|
||||
|
||||
@ -73,4 +73,37 @@ tests/cases/compiler/discriminantPropertyCheck.ts(65,9): error TS2532: Object is
|
||||
~~~~~
|
||||
!!! error TS2532: Object is possibly 'undefined'.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #27493
|
||||
|
||||
enum Types { Str = 1, Num = 2 }
|
||||
|
||||
type Instance = StrType | NumType;
|
||||
|
||||
interface StrType {
|
||||
type: Types.Str;
|
||||
value: string;
|
||||
length: number;
|
||||
}
|
||||
|
||||
interface NumType {
|
||||
type: Types.Num;
|
||||
value: number;
|
||||
}
|
||||
|
||||
function func2(inst: Instance) {
|
||||
while (true) {
|
||||
switch (inst.type) {
|
||||
case Types.Str: {
|
||||
inst.value.length;
|
||||
break;
|
||||
}
|
||||
case Types.Num: {
|
||||
inst.value.toExponential;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +65,40 @@ function foo6(x: Item) {
|
||||
if (x.foo !== undefined && x.qux) {
|
||||
x.foo.length; // Error, intervening discriminant guard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #27493
|
||||
|
||||
enum Types { Str = 1, Num = 2 }
|
||||
|
||||
type Instance = StrType | NumType;
|
||||
|
||||
interface StrType {
|
||||
type: Types.Str;
|
||||
value: string;
|
||||
length: number;
|
||||
}
|
||||
|
||||
interface NumType {
|
||||
type: Types.Num;
|
||||
value: number;
|
||||
}
|
||||
|
||||
function func2(inst: Instance) {
|
||||
while (true) {
|
||||
switch (inst.type) {
|
||||
case Types.Str: {
|
||||
inst.value.length;
|
||||
break;
|
||||
}
|
||||
case Types.Num: {
|
||||
inst.value.toExponential;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [discriminantPropertyCheck.js]
|
||||
function goo1(x) {
|
||||
@ -108,3 +141,23 @@ function foo6(x) {
|
||||
x.foo.length; // Error, intervening discriminant guard
|
||||
}
|
||||
}
|
||||
// Repro from #27493
|
||||
var Types;
|
||||
(function (Types) {
|
||||
Types[Types["Str"] = 1] = "Str";
|
||||
Types[Types["Num"] = 2] = "Num";
|
||||
})(Types || (Types = {}));
|
||||
function func2(inst) {
|
||||
while (true) {
|
||||
switch (inst.type) {
|
||||
case Types.Str: {
|
||||
inst.value.length;
|
||||
break;
|
||||
}
|
||||
case Types.Num: {
|
||||
inst.value.toExponential;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -228,3 +228,86 @@ function foo6(x: Item) {
|
||||
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #27493
|
||||
|
||||
enum Types { Str = 1, Num = 2 }
|
||||
>Types : Symbol(Types, Decl(discriminantPropertyCheck.ts, 66, 1))
|
||||
>Str : Symbol(Types.Str, Decl(discriminantPropertyCheck.ts, 70, 12))
|
||||
>Num : Symbol(Types.Num, Decl(discriminantPropertyCheck.ts, 70, 21))
|
||||
|
||||
type Instance = StrType | NumType;
|
||||
>Instance : Symbol(Instance, Decl(discriminantPropertyCheck.ts, 70, 31))
|
||||
>StrType : Symbol(StrType, Decl(discriminantPropertyCheck.ts, 72, 34))
|
||||
>NumType : Symbol(NumType, Decl(discriminantPropertyCheck.ts, 78, 1))
|
||||
|
||||
interface StrType {
|
||||
>StrType : Symbol(StrType, Decl(discriminantPropertyCheck.ts, 72, 34))
|
||||
|
||||
type: Types.Str;
|
||||
>type : Symbol(StrType.type, Decl(discriminantPropertyCheck.ts, 74, 19))
|
||||
>Types : Symbol(Types, Decl(discriminantPropertyCheck.ts, 66, 1))
|
||||
>Str : Symbol(Types.Str, Decl(discriminantPropertyCheck.ts, 70, 12))
|
||||
|
||||
value: string;
|
||||
>value : Symbol(StrType.value, Decl(discriminantPropertyCheck.ts, 75, 20))
|
||||
|
||||
length: number;
|
||||
>length : Symbol(StrType.length, Decl(discriminantPropertyCheck.ts, 76, 18))
|
||||
}
|
||||
|
||||
interface NumType {
|
||||
>NumType : Symbol(NumType, Decl(discriminantPropertyCheck.ts, 78, 1))
|
||||
|
||||
type: Types.Num;
|
||||
>type : Symbol(NumType.type, Decl(discriminantPropertyCheck.ts, 80, 19))
|
||||
>Types : Symbol(Types, Decl(discriminantPropertyCheck.ts, 66, 1))
|
||||
>Num : Symbol(Types.Num, Decl(discriminantPropertyCheck.ts, 70, 21))
|
||||
|
||||
value: number;
|
||||
>value : Symbol(NumType.value, Decl(discriminantPropertyCheck.ts, 81, 20))
|
||||
}
|
||||
|
||||
function func2(inst: Instance) {
|
||||
>func2 : Symbol(func2, Decl(discriminantPropertyCheck.ts, 83, 1))
|
||||
>inst : Symbol(inst, Decl(discriminantPropertyCheck.ts, 85, 15))
|
||||
>Instance : Symbol(Instance, Decl(discriminantPropertyCheck.ts, 70, 31))
|
||||
|
||||
while (true) {
|
||||
switch (inst.type) {
|
||||
>inst.type : Symbol(type, Decl(discriminantPropertyCheck.ts, 74, 19), Decl(discriminantPropertyCheck.ts, 80, 19))
|
||||
>inst : Symbol(inst, Decl(discriminantPropertyCheck.ts, 85, 15))
|
||||
>type : Symbol(type, Decl(discriminantPropertyCheck.ts, 74, 19), Decl(discriminantPropertyCheck.ts, 80, 19))
|
||||
|
||||
case Types.Str: {
|
||||
>Types.Str : Symbol(Types.Str, Decl(discriminantPropertyCheck.ts, 70, 12))
|
||||
>Types : Symbol(Types, Decl(discriminantPropertyCheck.ts, 66, 1))
|
||||
>Str : Symbol(Types.Str, Decl(discriminantPropertyCheck.ts, 70, 12))
|
||||
|
||||
inst.value.length;
|
||||
>inst.value.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
|
||||
>inst.value : Symbol(StrType.value, Decl(discriminantPropertyCheck.ts, 75, 20))
|
||||
>inst : Symbol(inst, Decl(discriminantPropertyCheck.ts, 85, 15))
|
||||
>value : Symbol(StrType.value, Decl(discriminantPropertyCheck.ts, 75, 20))
|
||||
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
break;
|
||||
}
|
||||
case Types.Num: {
|
||||
>Types.Num : Symbol(Types.Num, Decl(discriminantPropertyCheck.ts, 70, 21))
|
||||
>Types : Symbol(Types, Decl(discriminantPropertyCheck.ts, 66, 1))
|
||||
>Num : Symbol(Types.Num, Decl(discriminantPropertyCheck.ts, 70, 21))
|
||||
|
||||
inst.value.toExponential;
|
||||
>inst.value.toExponential : Symbol(Number.toExponential, Decl(lib.es5.d.ts, --, --))
|
||||
>inst.value : Symbol(NumType.value, Decl(discriminantPropertyCheck.ts, 81, 20))
|
||||
>inst : Symbol(inst, Decl(discriminantPropertyCheck.ts, 85, 15))
|
||||
>value : Symbol(NumType.value, Decl(discriminantPropertyCheck.ts, 81, 20))
|
||||
>toExponential : Symbol(Number.toExponential, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -232,3 +232,81 @@ function foo6(x: Item) {
|
||||
>length : number
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #27493
|
||||
|
||||
enum Types { Str = 1, Num = 2 }
|
||||
>Types : Types
|
||||
>Str : Types.Str
|
||||
>1 : 1
|
||||
>Num : Types.Num
|
||||
>2 : 2
|
||||
|
||||
type Instance = StrType | NumType;
|
||||
>Instance : Instance
|
||||
|
||||
interface StrType {
|
||||
type: Types.Str;
|
||||
>type : Types.Str
|
||||
>Types : any
|
||||
|
||||
value: string;
|
||||
>value : string
|
||||
|
||||
length: number;
|
||||
>length : number
|
||||
}
|
||||
|
||||
interface NumType {
|
||||
type: Types.Num;
|
||||
>type : Types.Num
|
||||
>Types : any
|
||||
|
||||
value: number;
|
||||
>value : number
|
||||
}
|
||||
|
||||
function func2(inst: Instance) {
|
||||
>func2 : (inst: Instance) => void
|
||||
>inst : Instance
|
||||
|
||||
while (true) {
|
||||
>true : true
|
||||
|
||||
switch (inst.type) {
|
||||
>inst.type : Types
|
||||
>inst : Instance
|
||||
>type : Types
|
||||
|
||||
case Types.Str: {
|
||||
>Types.Str : Types.Str
|
||||
>Types : typeof Types
|
||||
>Str : Types.Str
|
||||
|
||||
inst.value.length;
|
||||
>inst.value.length : number
|
||||
>inst.value : string
|
||||
>inst : StrType
|
||||
>value : string
|
||||
>length : number
|
||||
|
||||
break;
|
||||
}
|
||||
case Types.Num: {
|
||||
>Types.Num : Types.Num
|
||||
>Types : typeof Types
|
||||
>Num : Types.Num
|
||||
|
||||
inst.value.toExponential;
|
||||
>inst.value.toExponential : (fractionDigits?: number | undefined) => string
|
||||
>inst.value : number
|
||||
>inst : NumType
|
||||
>value : number
|
||||
>toExponential : (fractionDigits?: number | undefined) => string
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -66,4 +66,36 @@ function foo6(x: Item) {
|
||||
if (x.foo !== undefined && x.qux) {
|
||||
x.foo.length; // Error, intervening discriminant guard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #27493
|
||||
|
||||
enum Types { Str = 1, Num = 2 }
|
||||
|
||||
type Instance = StrType | NumType;
|
||||
|
||||
interface StrType {
|
||||
type: Types.Str;
|
||||
value: string;
|
||||
length: number;
|
||||
}
|
||||
|
||||
interface NumType {
|
||||
type: Types.Num;
|
||||
value: number;
|
||||
}
|
||||
|
||||
function func2(inst: Instance) {
|
||||
while (true) {
|
||||
switch (inst.type) {
|
||||
case Types.Str: {
|
||||
inst.value.length;
|
||||
break;
|
||||
}
|
||||
case Types.Num: {
|
||||
inst.value.toExponential;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user