@@ -7900,13 +7900,17 @@ namespace ts {
79007900 return TypeFacts.All;
79017901 }
79027902
7903- function getTypeWithFacts(type: Type, include: TypeFacts) {
7903+ function getTypeWithFacts(type: Type, include: TypeFacts, intersectForTypeParameters = false ) {
79047904 if (!(type.flags & TypeFlags.Union)) {
79057905 return getTypeFacts(type) & include ? type : neverType;
79067906 }
79077907 let firstType: Type;
7908+ let hasTypeParameter = false;
79087909 let types: Type[];
79097910 for (const t of (type as UnionType).types) {
7911+ if (t.flags & TypeFlags.TypeParameter) {
7912+ hasTypeParameter = true;
7913+ }
79107914 if (getTypeFacts(t) & include) {
79117915 if (!firstType) {
79127916 firstType = t;
@@ -7919,7 +7923,19 @@ namespace ts {
79197923 }
79207924 }
79217925 }
7922- return firstType ? types ? getUnionType(types) : firstType : neverType;
7926+ const narrowed = types ? getUnionType(types) :
7927+ firstType ? firstType : neverType;
7928+ // if there is a type parameter in the narrowed type,
7929+ // add an intersection with the members of the narrowed type so that the shape of the type is correct
7930+ if (type.flags & TypeFlags.Union &&
7931+ narrowed.flags & TypeFlags.Union &&
7932+ hasTypeParameter &&
7933+ intersectForTypeParameters) {
7934+ return getIntersectionType(types.concat([narrowed]));
7935+ }
7936+ else {
7937+ return narrowed;
7938+ }
79237939 }
79247940
79257941 function getTypeWithDefault(type: Type, defaultExpression: Expression) {
@@ -8183,7 +8199,7 @@ namespace ts {
81838199 let type = getTypeAtFlowNode(flow.antecedent);
81848200 if (type !== neverType) {
81858201 // If we have an antecedent type (meaning we're reachable in some way), we first
8186- // attempt to narrow the antecedent type. If that produces the nothing type, then
8202+ // attempt to narrow the antecedent type. If that produces the never type, then
81878203 // we take the type guard as an indication that control could reach here in a
81888204 // manner not understood by the control flow analyzer (e.g. a function argument
81898205 // has an invalid type, or a nested function has possibly made an assignment to a
@@ -8292,10 +8308,10 @@ namespace ts {
82928308
82938309 function narrowTypeByTruthiness(type: Type, expr: Expression, assumeTrue: boolean): Type {
82948310 if (isMatchingReference(reference, expr)) {
8295- return getTypeWithFacts(type, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy);
8311+ return getTypeWithFacts(type, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy, assumeTrue );
82968312 }
82978313 if (isMatchingPropertyAccess(expr)) {
8298- return narrowTypeByDiscriminant(type, <PropertyAccessExpression>expr, t => getTypeWithFacts(t, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy));
8314+ return narrowTypeByDiscriminant(type, <PropertyAccessExpression>expr, t => getTypeWithFacts(t, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy, assumeTrue ));
82998315 }
83008316 return type;
83018317 }
@@ -8353,7 +8369,7 @@ namespace ts {
83538369 value.kind === SyntaxKind.NullKeyword ?
83548370 assumeTrue ? TypeFacts.EQNull : TypeFacts.NENull :
83558371 assumeTrue ? TypeFacts.EQUndefined : TypeFacts.NEUndefined;
8356- return getTypeWithFacts(type, facts);
8372+ return getTypeWithFacts(type, facts, assumeTrue );
83578373 }
83588374 if (type.flags & TypeFlags.NotUnionOrUnit) {
83598375 return type;
@@ -8391,7 +8407,7 @@ namespace ts {
83918407 const facts = assumeTrue ?
83928408 getProperty(typeofEQFacts, literal.text) || TypeFacts.TypeofEQHostObject :
83938409 getProperty(typeofNEFacts, literal.text) || TypeFacts.TypeofNEHostObject;
8394- return getTypeWithFacts(type, facts);
8410+ return getTypeWithFacts(type, facts, assumeTrue );
83958411 }
83968412
83978413 function narrowTypeBySwitchOnDiscriminant(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number) {
0 commit comments