Skip to content

Commit 9e43183

Browse files
committed
Add fall-through test and correct comment about implied type
1 parent 0d79831 commit 9e43183

File tree

5 files changed

+375
-190
lines changed

5 files changed

+375
-190
lines changed

src/compiler/checker.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13594,10 +13594,10 @@ namespace ts {
1359413594
// }
1359513595
//
1359613596
// The implied type of the first clause number | string.
13597-
// The implied type of the second clause is string (but this doesn't get used).
13597+
// The implied type of the second clause is never, but this does not get just because it includes a default case.
1359813598
// The implied type of the third clause is boolean (number has already be caught).
1359913599
if (!(hasDefaultClause || (type.flags & TypeFlags.Union))) {
13600-
let impliedType = getTypeWithFacts(getUnionType(clauseWitnesses.map(text => typeofTypesByName.get(text) || neverType)), switchFacts);
13600+
let impliedType = getTypeWithFacts(getUnionType((<string[]>clauseWitnesses).map(text => typeofTypesByName.get(text) || neverType)), switchFacts);
1360113601
if (impliedType.flags & TypeFlags.Union) {
1360213602
impliedType = getAssignmentReducedType(impliedType as UnionType, getBaseConstraintOfType(type) || type);
1360313603
}
@@ -19027,30 +19027,35 @@ namespace ts {
1902719027
if (hasDefault) {
1902819028
// Value is not equal to any types after the active clause.
1902919029
for (let i = end; i < witnesses.length; i++) {
19030-
facts |= typeofNEFacts.get(witnesses[i]) || TypeFacts.TypeofNEHostObject;
19030+
const witness = witnesses[i];
19031+
facts |= (witness && typeofNEFacts.get(witness)) || TypeFacts.TypeofNEHostObject;
1903119032
}
1903219033
// Remove inequalities for types that appear in the
1903319034
// active clause because they appear before other
1903419035
// types collected so far.
1903519036
for (let i = start; i < end; i++) {
19036-
facts &= ~(typeofNEFacts.get(witnesses[i]) || 0);
19037+
const witness = witnesses[i];
19038+
facts &= ~((witness && typeofNEFacts.get(witness)) || 0);
1903719039
}
1903819040
// Add inequalities for types before the active clause unconditionally.
1903919041
for (let i = 0; i < start; i++) {
19040-
facts |= typeofNEFacts.get(witnesses[i]) || TypeFacts.TypeofNEHostObject;
19042+
const witness = witnesses[i];
19043+
facts |= (witness && typeofNEFacts.get(witness)) || TypeFacts.TypeofNEHostObject;
1904119044
}
1904219045
}
1904319046
// When in an active clause without default the set of
1904419047
// equalities is finite.
1904519048
else {
1904619049
// Add equalities for all types in the active clause.
1904719050
for (let i = start; i < end; i++) {
19048-
facts |= typeofEQFacts.get(witnesses[i]) || TypeFacts.TypeofEQHostObject;
19051+
const witness = witnesses[i];
19052+
facts |= (witness && typeofEQFacts.get(witness)) || TypeFacts.TypeofEQHostObject;
1904919053
}
1905019054
// Remove equalities for types that appear before the
1905119055
// active clause.
1905219056
for (let i = 0; i < start; i++) {
19053-
facts &= ~(typeofEQFacts.get(witnesses[i]) || 0);
19057+
const witness = witnesses[i];
19058+
facts &= ~((witness && typeofEQFacts.get(witness)) || 0);
1905419059
}
1905519060
}
1905619061
return facts;

tests/baselines/reference/narrowingByTypeofInSwitch.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ function assertAll(x: Basic) {
3535
return x;
3636
}
3737

38+
function assertStringOrNumber(x: string | number) {
39+
return x;
40+
}
41+
42+
function assertBooleanOrObject(x: boolean | object) {
43+
return x;
44+
}
45+
3846
type Basic = number | boolean | string | symbol | object | Function | undefined;
3947

4048
function testUnion(x: Basic) {
@@ -186,6 +194,22 @@ function switchOrderingWithDefault(x: string | number | boolean) {
186194
case 'number': return assertNever(x);
187195
}
188196
}
197+
198+
function fallThroughTest(x: string | number | boolean | object) {
199+
switch (typeof x) {
200+
case 'number':
201+
assertNumber(x)
202+
case 'string':
203+
assertStringOrNumber(x)
204+
break;
205+
default:
206+
assertObject(x);
207+
case 'number':
208+
case 'boolean':
209+
assertBooleanOrObject(x);
210+
break;
211+
}
212+
}
189213

190214

191215
//// [narrowingByTypeofInSwitch.js]
@@ -216,6 +240,12 @@ function assertUndefined(x) {
216240
function assertAll(x) {
217241
return x;
218242
}
243+
function assertStringOrNumber(x) {
244+
return x;
245+
}
246+
function assertBooleanOrObject(x) {
247+
return x;
248+
}
219249
function testUnion(x) {
220250
switch (typeof x) {
221251
case 'number':
@@ -425,3 +455,18 @@ function switchOrderingWithDefault(x) {
425455
case 'number': return assertNever(x);
426456
}
427457
}
458+
function fallThroughTest(x) {
459+
switch (typeof x) {
460+
case 'number':
461+
assertNumber(x);
462+
case 'string':
463+
assertStringOrNumber(x);
464+
break;
465+
default:
466+
assertObject(x);
467+
case 'number':
468+
case 'boolean':
469+
assertBooleanOrObject(x);
470+
break;
471+
}
472+
}

0 commit comments

Comments
 (0)