Skip to content

Commit 00376f4

Browse files
committed
Narrow non-union types to ensure consistent results
1 parent c90b0fe commit 00376f4

1 file changed

Lines changed: 12 additions & 7 deletions

File tree

src/compiler/checker.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7699,6 +7699,12 @@ namespace ts {
76997699
return source.flags & TypeFlags.Union ? !forEach((<UnionType>source).types, t => !contains(types, t)) : contains(types, source);
77007700
}
77017701

7702+
function filterType(type: Type, f: (t: Type) => boolean): Type {
7703+
return type.flags & TypeFlags.Union ?
7704+
getUnionType(filter((<UnionType>type).types, f)) :
7705+
f(type) ? type : neverType;
7706+
}
7707+
77027708
function getFlowTypeOfReference(reference: Node, declaredType: Type, assumeInitialized: boolean, includeOuterFunctions: boolean) {
77037709
let key: string;
77047710
if (!reference.flowNode || assumeInitialized && !(declaredType.flags & TypeFlags.Narrowable)) {
@@ -7944,7 +7950,7 @@ namespace ts {
79447950

79457951
function narrowTypeByDiscriminant(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
79467952
// We have '==', '!=', '===', or '!==' operator with property access on left
7947-
if (!(type.flags & TypeFlags.Union) || !isMatchingReference(reference, (<PropertyAccessExpression>expr.left).expression)) {
7953+
if (!isMatchingReference(reference, (<PropertyAccessExpression>expr.left).expression)) {
79487954
return type;
79497955
}
79507956
const propName = (<PropertyAccessExpression>expr.left).name.text;
@@ -7961,17 +7967,17 @@ namespace ts {
79617967
assumeTrue = !assumeTrue;
79627968
}
79637969
if (assumeTrue) {
7964-
return getUnionType(filter((<UnionType>type).types, t => areTypesComparable(getTypeOfPropertyOfType(t, propName), discriminantType)));
7970+
return filterType(type, t => areTypesComparable(getTypeOfPropertyOfType(t, propName), discriminantType));
79657971
}
79667972
if (discriminantType.flags & TypeFlags.StringLiteral) {
7967-
return getUnionType(filter((<UnionType>type).types, t => getTypeOfPropertyOfType(t, propName) !== discriminantType));
7973+
return filterType(type, t => getTypeOfPropertyOfType(t, propName) !== discriminantType);
79687974
}
79697975
return type;
79707976
}
79717977

79727978
function narrowTypeBySwitchOnDiscriminant(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number) {
79737979
// We have switch statement with property access expression
7974-
if (!(type.flags & TypeFlags.Union) || !isMatchingReference(reference, (<PropertyAccessExpression>switchStatement.expression).expression)) {
7980+
if (!isMatchingReference(reference, (<PropertyAccessExpression>switchStatement.expression).expression)) {
79757981
return type;
79767982
}
79777983
const propName = (<PropertyAccessExpression>switchStatement.expression).name.text;
@@ -7983,16 +7989,15 @@ namespace ts {
79837989
if (!switchTypes.length) {
79847990
return type;
79857991
}
7986-
const types = (<UnionType>type).types;
79877992
const clauseTypes = switchTypes.slice(clauseStart, clauseEnd);
79887993
const hasDefaultClause = clauseStart === clauseEnd || contains(clauseTypes, undefined);
79897994
const caseTypes = hasDefaultClause ? filter(clauseTypes, t => !!t) : clauseTypes;
79907995
const discriminantType = caseTypes.length ? getUnionType(caseTypes) : undefined;
7991-
const caseType = discriminantType && getUnionType(filter(types, t => isTypeComparableTo(discriminantType, getTypeOfPropertyOfType(t, propName))));
7996+
const caseType = discriminantType && filterType(type, t => isTypeComparableTo(discriminantType, getTypeOfPropertyOfType(t, propName)));
79927997
if (!hasDefaultClause) {
79937998
return caseType;
79947999
}
7995-
const defaultType = getUnionType(filter(types, t => !eachTypeContainedIn(getTypeOfPropertyOfType(t, propName), switchTypes)));
8000+
const defaultType = filterType(type, t => !eachTypeContainedIn(getTypeOfPropertyOfType(t, propName), switchTypes));
79968001
return caseType ? getUnionType([caseType, defaultType]) : defaultType;
79978002
}
79988003

0 commit comments

Comments
 (0)