@@ -7327,18 +7327,6 @@ namespace ts {
73277327 return false;
73287328 }
73297329
7330- function typeMaybeSubtypeOf(source: Type, target: Type) {
7331- if (!(source.flags & TypeFlags.Union)) {
7332- return isTypeSubtypeOf(source, target);
7333- }
7334- for (const t of (<UnionType>source).types) {
7335- if (isTypeSubtypeOf(t, target)) {
7336- return true;
7337- }
7338- }
7339- return false;
7340- }
7341-
73427330 // Remove those constituent types of declaredType to which no constituent type of assignedType is assignable.
73437331 // For example, when a variable of type number | string | boolean is assigned a value of type number | boolean,
73447332 // we remove type string.
@@ -7769,28 +7757,26 @@ namespace ts {
77697757 }
77707758
77717759 function getNarrowedType(type: Type, candidate: Type, assumeTrue: boolean) {
7772- if (typeMaybeSubtypeOf(type, candidate)) {
7773- // If the current type, or a constituent of the current type, is a subtype of
7774- // the candidate type then the current type contains the most specific information.
7775- // and we simply filter out constituents that aren't applicable. For example,
7776- // if the current type is string | string[] and the candidate type is any[],
7777- // we filter out string.
7760+ if (!assumeTrue) {
77787761 return type.flags & TypeFlags.Union ?
7779- getUnionType(filter((<UnionType>type).types, t => isTypeSubtypeOf(t, candidate) === assumeTrue)) :
7780- assumeTrue ? type : emptyUnionType;
7781- }
7782- if (assumeTrue) {
7783- // In the true branch of the remaining cases, if the candidate type is assignable
7784- // to the current type, then we narrow to the candidate type. Otherwise, we narrow
7785- // to an empty type (because we now know the types are completely unrelated). For
7786- // example, if the current type is Object and the candidate type is string[], we
7787- // narrow to string[]. But if the current type is string and the candidate is
7788- // string[], we narrow to the empty type.
7789- const targetType = type.flags & TypeFlags.TypeParameter ? getApparentType(type) : type;
7790- return isTypeAssignableTo(candidate, targetType) ? candidate : emptyUnionType;
7791- }
7792- // In the false branch of the remaining cases we leave the type unchanged.
7793- return type;
7762+ getUnionType(filter((<UnionType>type).types, t => !isTypeSubtypeOf(t, candidate))) :
7763+ type;
7764+ }
7765+ // If the current type is a union type, remove all constituents that aren't assignable to
7766+ // the candidate type. If one or more constituents remain, return a union of those.
7767+ if (type.flags & TypeFlags.Union) {
7768+ const assignableConstituents = filter((<UnionType>type).types, t => isTypeAssignableTo(t, candidate));
7769+ if (assignableConstituents.length) {
7770+ return getUnionType(assignableConstituents);
7771+ }
7772+ }
7773+ // If the candidate type is assignable to the target type, narrow to the candidate type.
7774+ // Otherwise, if the current type is assignable to the candidate, keep the current type.
7775+ // Otherwise, the types are completely unrelated, so narrow to the empty type.
7776+ const targetType = type.flags & TypeFlags.TypeParameter ? getApparentType(type) : type;
7777+ return isTypeAssignableTo(candidate, targetType) ? candidate :
7778+ isTypeAssignableTo(type, candidate) ? type :
7779+ emptyUnionType;
77947780 }
77957781
77967782 function narrowTypeByTypePredicate(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type {
0 commit comments