Skip to content

Commit 7a47248

Browse files
committed
Produce intersection types for spreads with generic types
1 parent 24febc2 commit 7a47248

File tree

1 file changed

+22
-2
lines changed

1 file changed

+22
-2
lines changed

src/compiler/checker.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9840,6 +9840,10 @@ namespace ts {
98409840
return symbol ? getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) : undefined;
98419841
}
98429842

9843+
function isNonGenericObjectType(type: Type) {
9844+
return !!(type.flags & TypeFlags.Object) && !isGenericMappedType(type);
9845+
}
9846+
98439847
/**
98449848
* Since the source of spread types are object literals, which are not binary,
98459849
* this function should be called in a left folding style, with left = previous result of getSpreadType
@@ -9868,6 +9872,23 @@ namespace ts {
98689872
return left;
98699873
}
98709874

9875+
if (isGenericObjectType(left) || isGenericObjectType(right)) {
9876+
if (isEmptyObjectType(left)) {
9877+
return right;
9878+
}
9879+
// When the left type is an intersection, we may need to merge the last constituent of the
9880+
// intersection with the right type. For example when the left type is 'T & { a: string }'
9881+
// and the right type is '{ b: string }' we produce 'T & { a: string, b: string }'.
9882+
if (left.flags & TypeFlags.Intersection) {
9883+
const types = (<IntersectionType>left).types;
9884+
const lastLeft = types[types.length - 1];
9885+
if (isNonGenericObjectType(lastLeft) && isNonGenericObjectType(right)) {
9886+
return getIntersectionType(concatenate(types.slice(0, types.length - 1), [getSpreadType(lastLeft, right, symbol, typeFlags, objectFlags)]));
9887+
}
9888+
}
9889+
return getIntersectionType([left, right]);
9890+
}
9891+
98719892
const members = createSymbolTable();
98729893
const skippedPrivateMembers = createUnderscoreEscapedMap<boolean>();
98739894
let stringIndexInfo: IndexInfo | undefined;
@@ -17697,9 +17718,8 @@ namespace ts {
1769717718
}
1769817719

1769917720
function isValidSpreadType(type: Type): boolean {
17700-
return !!(type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.NonPrimitive) ||
17721+
return !!(type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.NonPrimitive | TypeFlags.Object | TypeFlags.InstantiableNonPrimitive) ||
1770117722
getFalsyFlags(type) & TypeFlags.DefinitelyFalsy && isValidSpreadType(removeDefinitelyFalsyTypes(type)) ||
17702-
type.flags & TypeFlags.Object && !isGenericMappedType(type) ||
1770317723
type.flags & TypeFlags.UnionOrIntersection && every((<UnionOrIntersectionType>type).types, isValidSpreadType));
1770417724
}
1770517725

0 commit comments

Comments
 (0)