Skip to content

Commit

Permalink
Add fall-through test and correct comment about implied type
Browse files Browse the repository at this point in the history
  • Loading branch information
jack-williams committed May 23, 2018
1 parent 0d79831 commit 9e43183
Show file tree
Hide file tree
Showing 5 changed files with 375 additions and 190 deletions.
19 changes: 12 additions & 7 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13594,10 +13594,10 @@ namespace ts {
// }
//
// The implied type of the first clause number | string.
// The implied type of the second clause is string (but this doesn't get used).
// The implied type of the second clause is never, but this does not get just because it includes a default case.
// The implied type of the third clause is boolean (number has already be caught).
if (!(hasDefaultClause || (type.flags & TypeFlags.Union))) {
let impliedType = getTypeWithFacts(getUnionType(clauseWitnesses.map(text => typeofTypesByName.get(text) || neverType)), switchFacts);
let impliedType = getTypeWithFacts(getUnionType((<string[]>clauseWitnesses).map(text => typeofTypesByName.get(text) || neverType)), switchFacts);
if (impliedType.flags & TypeFlags.Union) {
impliedType = getAssignmentReducedType(impliedType as UnionType, getBaseConstraintOfType(type) || type);
}
Expand Down Expand Up @@ -19027,30 +19027,35 @@ namespace ts {
if (hasDefault) {
// Value is not equal to any types after the active clause.
for (let i = end; i < witnesses.length; i++) {
facts |= typeofNEFacts.get(witnesses[i]) || TypeFacts.TypeofNEHostObject;
const witness = witnesses[i];
facts |= (witness && typeofNEFacts.get(witness)) || TypeFacts.TypeofNEHostObject;
}
// Remove inequalities for types that appear in the
// active clause because they appear before other
// types collected so far.
for (let i = start; i < end; i++) {
facts &= ~(typeofNEFacts.get(witnesses[i]) || 0);
const witness = witnesses[i];
facts &= ~((witness && typeofNEFacts.get(witness)) || 0);
}
// Add inequalities for types before the active clause unconditionally.
for (let i = 0; i < start; i++) {
facts |= typeofNEFacts.get(witnesses[i]) || TypeFacts.TypeofNEHostObject;
const witness = witnesses[i];
facts |= (witness && typeofNEFacts.get(witness)) || TypeFacts.TypeofNEHostObject;
}
}
// When in an active clause without default the set of
// equalities is finite.
else {
// Add equalities for all types in the active clause.
for (let i = start; i < end; i++) {
facts |= typeofEQFacts.get(witnesses[i]) || TypeFacts.TypeofEQHostObject;
const witness = witnesses[i];
facts |= (witness && typeofEQFacts.get(witness)) || TypeFacts.TypeofEQHostObject;
}
// Remove equalities for types that appear before the
// active clause.
for (let i = 0; i < start; i++) {
facts &= ~(typeofEQFacts.get(witnesses[i]) || 0);
const witness = witnesses[i];
facts &= ~((witness && typeofEQFacts.get(witness)) || 0);
}
}
return facts;
Expand Down
45 changes: 45 additions & 0 deletions tests/baselines/reference/narrowingByTypeofInSwitch.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ function assertAll(x: Basic) {
return x;
}

function assertStringOrNumber(x: string | number) {
return x;
}

function assertBooleanOrObject(x: boolean | object) {
return x;
}

type Basic = number | boolean | string | symbol | object | Function | undefined;

function testUnion(x: Basic) {
Expand Down Expand Up @@ -186,6 +194,22 @@ function switchOrderingWithDefault(x: string | number | boolean) {
case 'number': return assertNever(x);
}
}

function fallThroughTest(x: string | number | boolean | object) {
switch (typeof x) {
case 'number':
assertNumber(x)
case 'string':
assertStringOrNumber(x)
break;
default:
assertObject(x);
case 'number':
case 'boolean':
assertBooleanOrObject(x);
break;
}
}


//// [narrowingByTypeofInSwitch.js]
Expand Down Expand Up @@ -216,6 +240,12 @@ function assertUndefined(x) {
function assertAll(x) {
return x;
}
function assertStringOrNumber(x) {
return x;
}
function assertBooleanOrObject(x) {
return x;
}
function testUnion(x) {
switch (typeof x) {
case 'number':
Expand Down Expand Up @@ -425,3 +455,18 @@ function switchOrderingWithDefault(x) {
case 'number': return assertNever(x);
}
}
function fallThroughTest(x) {
switch (typeof x) {
case 'number':
assertNumber(x);
case 'string':
assertStringOrNumber(x);
break;
default:
assertObject(x);
case 'number':
case 'boolean':
assertBooleanOrObject(x);
break;
}
}
Loading

0 comments on commit 9e43183

Please sign in to comment.