Overly strict matching of function overloads to function intersections, and an algorithm that could help #57087
Labels
Awaiting More Feedback
This means we'd like to hear from more people who would be helped by this feature
Suggestion
An idea for TypeScript
π Search Terms
function intersections
matching function intersections to function overloads
β Viability Checklist
β Suggestion
Intersections of functions occur naturally when the superposition of two or more functions which take function as arguments.
Example: naturally occuring intersection of functions as parameters
In this example it is the function
x.g
that has an intersection of functions as a parameter.In the general case a argument function passed to such an intersection of function parameters may need to be an overload, and TypeScript has an algorithm to type check that argument (the function overload) against the parameter (the intersection of functions). However, the algorithm is too strict in some cases, and rejects some valid overloads. Examples of valid overloads that are rejected are shown, and an algorithm that would pass those valid overloads is proposed.
π Motivating Example
The value of
x.g
is a function that takes a function as an argument. Whenx
is the superpostion (union) of twoFMap
objects, the intersection of the argument types of the two functions is the type of the argument of the intersection function. Becauseg
takes a function argument, the parameter type ofg
is the intersection of two functions.What exactly does intersection of two functions mean?
When we say union of two functions it is just stating a fact about the flow analysis. The function itself is not a new function, the user need to provide no new coding. Instead, the compiler recognizes that only the interscetion of the argument types of the two functions is valid for the union function:
In contrast, in the general case, the "intersection" function that is passed to
x.g
may need to be a new function with an input domain that encompasses the input domains of the two functions. In this case neitherx1.f
norx2.f
alone satisfies that condition:The user must provide a new function that has the union of the input domains of
x1.f
andx2.f
:Try it
x.g(ft1)
is an error because single functionft1
signature has a wider input-output map than the intersection of the input-output maps ofx1.f
andx2.f
.Actually the implementation is fine - it does deliver the required narrowness of the required input-output map. We just need to write a narrower overload signature to match the parameter for
x.g
:Example 1
Unfortunately - it's still an error, but the error message is different. However, it doesn't need to be an error; the specified overload is sound. No error here would be preferable.
If we make the overload declaration match intersection shape exactly (note: intersection member order is a free parameter), then it works:
which is good, but we shouldn't have to do that.
Example 2
Again, this doesn't need to be an error; the specified overload is sound. No error here would be preferable.
Example 3
An algorithm that would pass all the above examples:
f = { f[0];f[1]; ...}
is a valid argument to a functiong = g[0] && g[1] && ...
f
at least includes the whole domain ofg
In words, the algorithm passes if the overload
f
is both large enough to support the domain ofg
, and small enough to be a subset of the input-output mappings ofg
.π» Use Cases
Parameters which are function intersections generally require arguments which are described by function overloads.
This proposal showed a class of valid overloads that are currently rejected by the compiler, and offers a proposed algorithm that would accept them.
An
any
cast.Additional Information
This proposal doesn't include information about the current algorithm, and the reasons why it was chosen.
It is not clear whether the current algorithm is or is not the best choice due to other factors not considered here, but it is clear that it is not the only choice.
The text was updated successfully, but these errors were encountered: