Spread & rest over intersection and unions#12552
Conversation
…nd distribute spread&rest over unions
| @@ -0,0 +1,38 @@ | |||
| === tests/cases/compiler/restIntersectionOrIntersection.ts === | |||
There was a problem hiding this comment.
should be named restIntersectionOrUnion.ts, right?
sandersn
left a comment
There was a problem hiding this comment.
You should copy some fourslash tests from the original spread PR, pre-object-only. In particular, rename was tricky, as I recall.
sandersn
left a comment
There was a problem hiding this comment.
Couple of tiny updates, otherwise looks good.
src/compiler/checker.ts
Outdated
| return getUnionType(map(types, t => getSpreadType(left, t, isFromObjectLiteral))); | ||
| } | ||
| else { | ||
| right = emptyObjectType |
| @@ -68,11 +66,7 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(61,14): error TS269 | |||
|
|
|||
| // null, undefined and primitives are not allowed | |||
|
@ahejlsberg can you take a look |
src/compiler/checker.ts
Outdated
| return anyType; | ||
| } | ||
|
|
||
| if (left.flags & TypeFlags.Union) { |
There was a problem hiding this comment.
nit: these two parts of code for left and right looks quite similar, can they be extracted to a function?
src/compiler/checker.ts
Outdated
| } | ||
|
|
||
| if (left.flags & TypeFlags.Union) { | ||
| const types = filter((<UnionType>left).types, t => !(t.flags & TypeFlags.Nullable)); |
There was a problem hiding this comment.
this pattern filter out nullable types is repeated at least 3 times
src/compiler/checker.ts
Outdated
| return anyType; | ||
| } | ||
|
|
||
| if (left.flags & TypeFlags.Union) { |
There was a problem hiding this comment.
You can replace all of these new lines with just this:
left = filterType(left, t => !(t.flags & TypeFlags.Nullable));
if (left.flags & TypeFlags.Never) {
return right;
}
right = filterType(right, t => !(t.flags & TypeFlags.Nullable));
if (right.flags & TypeFlags.Never) {
return left;
}
if (left.flags & TypeFlags.Union) {
return mapType(left, t => getSpreadType(t, right, isFromObjectLiteral));
}
if (right.flags & TypeFlags.Union) {
return mapType(right, t => getSpreadType(left, t, isFromObjectLiteral));
}| } | ||
| } | ||
|
|
||
| function isValidSpreadType(type: Type): boolean { |
There was a problem hiding this comment.
The functional style is a lot shorter:
function isValidSpreadType(type: Type): boolean {
return !!(type.flags & (TypeFlags.Any | TypeFlags.Null | TypeFlags.Undefined) ||
type.flags & TypeFlags.Object && !isGenericMappedType(type) ||
type.flags & TypeFlags.UnionOrIntersection && !forEach((<UnionOrIntersectionType>type).types, t => !isValidSpreadType(t)));
}
src/compiler/checker.ts
Outdated
| return symbol ? getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) : undefined; | ||
| } | ||
|
|
||
| function filterNulableTypes(union: UnionType): Type[] { |
There was a problem hiding this comment.
Spelling. Not sure you need to keep this function, but if you do, have it operate on any kind of type in the same way as mapType and filterType.
src/compiler/checker.ts
Outdated
|
|
||
| function isValidSpreadType(type: Type): boolean { | ||
| if (type.flags & (TypeFlags.Any | TypeFlags.Null | TypeFlags.Undefined)) { | ||
| return true; |
Port null/undefined support in __rest from microsoft/TypeScript#12552
|
👍 |
Fixes #12520 , #12534 and #12460
//CC @sandersn