-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Improve checking of complex rest parameter types #26676
Conversation
I just tested the PR (commit 349bee9) on the bad example from #26110 (comment) and I get no compile errors. Is this expected? |
For anyone watching, the discussion of the unsoundness continues at #26110 (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.
I like the change. Just a few nits in the code.
src/compiler/checker.ts
Outdated
const sourceRestType = getNonArrayRestType(source); | ||
const targetRestType = getNonArrayRestType(target); | ||
if (sourceRestType && targetRestType && sourceCount !== targetCount) { | ||
// We're not able to relate misaliged complex rest parameters |
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.
typo:misaligned
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.
Will fix.
@@ -12693,6 +12699,11 @@ namespace ts { | |||
return type.target.hasRestElement ? type.typeArguments![type.target.typeParameters!.length - 1] : undefined; | |||
} | |||
|
|||
function getRestArrayTypeOfTupleType(type: TupleTypeReference) { |
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.
since this is only used in getEffectiveRestType
, can you move this near to it?
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.
I like it where it is, it is closely related to the function just above.
} | ||
} | ||
} | ||
if (restType) { | ||
const spreadType = getSpreadArgumentType(args, argCount, args.length, restType, /*context*/ undefined); | ||
const errorNode = reportErrors ? argCount < args.length ? args[argCount] : node : undefined; |
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.
I'm not a fan of x ? y : e1 : e2 : undefined
patterns. Would reportErrors && (argCount < args.length ? ...)
work?
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.
Sort of agree, but the rewrite you suggest doesn't work because it injects a false
into the union type. Ima keepit.
With this PR we properly check rest parameters of any subtype of
any[]
, including user-defined array types and unions of tuple types. In cases where a rest parameter type is not exactly aT[]
or a tuple type, we now collect the corresponding remainder of the argument list as a tuple type and then check that this tuple type is assignable to the rest parameter type.Effectively, rest parameters typed as unions of tuple types provide a form of overloading expressed in a single function type signature. Unlike regular overloading, generic rest parameters can be used to form composed overloads:
Function type relations have been improved to handle rest parameters of union types:
Note that we currently don't "normalize" misaligned rest parameters. It would certainly be possible to do so, but it is not clear that the additional complexity is merited.
Fixes #26110.
Fixes #26491.