-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Spread & rest over intersection and unions #12552
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…nd distribute spread&rest over unions
| @@ -0,0 +1,38 @@ | |||
| === tests/cases/compiler/restIntersectionOrIntersection.ts === | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be named restIntersectionOrUnion.ts, right?
sandersn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couple of tiny updates, otherwise looks good.
src/compiler/checker.ts
Outdated
| return getUnionType(map(types, t => getSpreadType(left, t, isFromObjectLiteral))); | ||
| } | ||
| else { | ||
| right = emptyObjectType |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing semicolon
| !!! error TS2300: Duplicate identifier 'b'. | ||
| let duplicatedSpread = { ...o, ...o } | ||
|
|
||
| // null, undefined and primitives are not allowed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you update this comment?
|
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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)));
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks. fixed.
src/compiler/checker.ts
Outdated
| return symbol ? getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) : undefined; | ||
| } | ||
|
|
||
| function filterNulableTypes(union: UnionType): Type[] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC this should also fix #12460
Port null/undefined support in __rest from microsoft/TypeScript#12552
|
👍 |
Fixes #12520 , #12534 and #12460
//CC @sandersn