-
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
Contextually type unions of differing signatures, rather than giving up #17819
Contextually type unions of differing signatures, rather than giving up #17819
Conversation
Might fix #17127? |
383ac75
to
c6adbf8
Compare
c6adbf8
to
7167a3d
Compare
Per brief post-design meeting discussion from the week before last, I've "ripped off the bandaid", as it were, and now combine signatures regardless of if the source was a union or not, for the purpose of contextual typing. As:
I'll report on how this affects RWC results shortly. |
33cc0c5
to
c11d001
Compare
The mentioned issues are different enough in details, would this fix this should-be-common case? interface NodeCallback<T> {
(err: any, result?: undefined | null): void;
(err: undefined | null, result: T): void;
}
const cb: NodeCallback<T> = (err, result) => { // 'err', 'result' are implicitly any
// ...
}; Node-style callbacks are (obviously!) very commonly used, and at the moment have a too-weak type on the consumer (callback caller) side, presumably because otherwise actually providing the callback is too verbose. |
Thanks for your contribution. This PR has not been updated in a while and cannot be automatically merged at the time being. For housekeeping purposes we are closing stale PRs. If you'd still like to continue working on this PR, please leave a message and one of the maintainers can reopen it. |
If a function expression was contextually typed by multiple signatures, and those signatures were not sufficiently similar, we gave up on contextually typing the function, according to our specification. This results in a
noImplicitAny
error, if enabled. With this change, we generate a synthetic signature whose arguments are the union of all possibilities for those arguments, and whose return is the intersection of all of the returns those expect (🚲 🏠 - since contextual typing is only performed on implementations, it is likely safe and more useful to use a union of return types instead, like we do for similar signatures; but I'd like some feedback before jumping to that conclusion), and use that to inform contextual typing decisions, rather than giving up. This gives better inferences for the arguments of function expressions contextualized by non-like signatures, however the downside is that this is less permissive outside of strict mode than we were before (as previously it would be typedany
).If this is too much of a breaking change (see
functionExpressionContextualTyping1.errors.txt
), I think it is OK to have this gated behind thenoImplicitAny
flag, since the inference result prior to this would have been an error anyway.Fixes #16019. (The root issue was the that interfaces used yielded two call signatures for a
ref
, each of which with a different parameter type; causing inference to fail.)This is also tangentially related to #7763, as the same signature-merging methodology could be used for the inference of the implementation signature.
Additionally, this could help remove the design limitation in the root issue of #11936 (by fixing the contextual typing - not changing overload resolution; all that would need to be done is to treat overloads, once contextual signature finding has failed, the same as a union of those signatures).
TL;DR:
With this change, given this code:
We now infer the type of
x
asA | B
instead ofany
.