diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f182ce899ce..8b53ecbf191 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7669,17 +7669,18 @@ namespace ts { const type = flow.kind === FlowKind.LoopLabel ? getTypeAtFlowNodeCached(antecedent) : getTypeAtFlowNode(antecedent); - if (type) { - // If the type at a particular antecedent path is the declared type and the - // reference is known to always be assigned (i.e. when declared and initial types - // are the same), there is no reason to process more antecedents since the only - // possible outcome is subtypes that will be removed in the final union type anyway. - if (type === declaredType && declaredType === initialType) { - return type; - } - if (!contains(antecedentTypes, type)) { - antecedentTypes.push(type); - } + if (!type) { + break; + } + // If the type at a particular antecedent path is the declared type and the + // reference is known to always be assigned (i.e. when declared and initial types + // are the same), there is no reason to process more antecedents since the only + // possible outcome is subtypes that will be removed in the final union type anyway. + if (type === declaredType && declaredType === initialType) { + return type; + } + if (!contains(antecedentTypes, type)) { + antecedentTypes.push(type); } } return antecedentTypes.length === 0 ? undefined : diff --git a/tests/baselines/reference/controlFlowLoopAnalysis.errors.txt b/tests/baselines/reference/controlFlowLoopAnalysis.errors.txt new file mode 100644 index 00000000000..21bf6b1c19a --- /dev/null +++ b/tests/baselines/reference/controlFlowLoopAnalysis.errors.txt @@ -0,0 +1,39 @@ +tests/cases/compiler/controlFlowLoopAnalysis.ts(13,25): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. + Type 'undefined' is not assignable to type 'number'. + + +==== tests/cases/compiler/controlFlowLoopAnalysis.ts (1 errors) ==== + + // Repro from #8418 + + let cond: boolean; + + function foo(x: number): number { return 1; } + + function test1() { + let x: number | undefined; + while (cond) { + while (cond) { + while (cond) { + x = foo(x); + ~ +!!! error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. +!!! error TS2345: Type 'undefined' is not assignable to type 'number'. + } + } + x = 1; + } + } + + // Repro from #8418 + + function test2() { + let x: number | undefined; + x = 1; + while (cond) { + while (cond) { + x = foo(x); + } + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/controlFlowLoopAnalysis.js b/tests/baselines/reference/controlFlowLoopAnalysis.js new file mode 100644 index 00000000000..3cf2ce2caac --- /dev/null +++ b/tests/baselines/reference/controlFlowLoopAnalysis.js @@ -0,0 +1,58 @@ +//// [controlFlowLoopAnalysis.ts] + +// Repro from #8418 + +let cond: boolean; + +function foo(x: number): number { return 1; } + +function test1() { + let x: number | undefined; + while (cond) { + while (cond) { + while (cond) { + x = foo(x); + } + } + x = 1; + } +} + +// Repro from #8418 + +function test2() { + let x: number | undefined; + x = 1; + while (cond) { + while (cond) { + x = foo(x); + } + } +} + + +//// [controlFlowLoopAnalysis.js] +// Repro from #8418 +var cond; +function foo(x) { return 1; } +function test1() { + var x; + while (cond) { + while (cond) { + while (cond) { + x = foo(x); + } + } + x = 1; + } +} +// Repro from #8418 +function test2() { + var x; + x = 1; + while (cond) { + while (cond) { + x = foo(x); + } + } +} diff --git a/tests/cases/compiler/controlFlowLoopAnalysis.ts b/tests/cases/compiler/controlFlowLoopAnalysis.ts new file mode 100644 index 00000000000..60cb9436006 --- /dev/null +++ b/tests/cases/compiler/controlFlowLoopAnalysis.ts @@ -0,0 +1,31 @@ +// @strictNullChecks: true + +// Repro from #8418 + +let cond: boolean; + +function foo(x: number): number { return 1; } + +function test1() { + let x: number | undefined; + while (cond) { + while (cond) { + while (cond) { + x = foo(x); + } + } + x = 1; + } +} + +// Repro from #8418 + +function test2() { + let x: number | undefined; + x = 1; + while (cond) { + while (cond) { + x = foo(x); + } + } +}