-
Notifications
You must be signed in to change notification settings - Fork 12.8k
[Bug] & [Feature Request] ?? Compose Function Types using Generics / inferring fn params using generics #37835
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
Comments
Have same problem, I came up with a simpler example: function fn<T>(a: number, b: T): T {
return b;
}
function fnWrapper<T>(a: string, b: Parameters<typeof fn<T>>[1]): ReturnType<typeof fn<T>> {
return fn(parseInt(a), b);
} I want to make a new function that is exactly the same as fn, but where the first parameter is string instead of number. This example doesn't work because fn is generic and Unrelated to this, is there a way to |
@DanielHoffmann I could make this work using the following code (Playground Link): function fn<T>(a: number, b: T): T {
return b;
}
function withStringArg<A extends any[], R>(fn: (a: number, ...args: A) => R) {
return (a: string, ...rest: A) => fn(parseInt(a), ...rest);
}
const fnWrapper = withStringArg(fn);
const b = fnWrapper("0", true); // b has type `true`
You can achieve this using constructs like |
I don't think this is a problem if it binds like
Agree! 😃 |
Looks like this issue is fixed by 4.7 new feature instantiation expression? |
Well it actually is not - but it is close enough! It models half of what i needed. |
Note: This got a bit verbose and detailed -- the
Use Case
at the bottom may be the clearest example of the goal here.Hey y'all!! Running into a situation where I need to infer a property of a function but it needs to use another property (using a Generic) of the function to properly determine the type. I am guessing this isn't currently possible based on my testing but think it would be a pretty good thing to allow?
TypeScript Version: 3.8.3
Search Terms:
Code
Typescript Playground
Expected behavior:
Ability to compose types to extract an argument from a function which is able to utilize the value of a generic to do so.
Actual behavior:
There are some weird bugs where the types end up being wrong in multiple situations - sometimes it returns never when it shouldnt etc. This appears to have to do with the types that
data
are. If all the types of the possibilities are not compatible then it will not return anything which does not seem to be correct (@see typescript playground where it returns both asnever
now)Essentially what would be nice, is given a function:
We have the ability to get the function with static types by defining the generics like we can do when calling the functions. So essentially it may look like this? not sure...
Similar Issues:
#37181 is similar
Proposal
So inline with #37181 - but expanding on it a bit, the idea would be to allow composing a type by providing the values of the generics for a function and receiving a
typeof fn
which would be the signature it would have should that generic be provided to it.To visualize this I simplified the case here a bit. Clearly there are ways to achieve this specific functionality but the concept of being able to pass generics which can be passed down has wide implications and shouldn't be too complex to implement (although I don't really know that is the case lol)
So given the below (which currently doesnt work as FooProps is
never
)the goal is that the generic can be used to infer the fn. When calling the expression this does work as expected:
So essentially with this proposal this would evaluate like this:
A couple things this would enforce:
type GetPropsFor<T> = typeof fn<T> ...
would require that GetPropsFor's genericT
is assignable to fn's genericT
typeof fn<T>
would essentially create a type signature where the genericT
is substituted infn
and the resulting value and return type is provided in response.It would be possible in these cases to define less generics than the fn itself defines in the case we simply want to define a specific value. I believe flow has a concept for this using
_
wherefn<_, string, _>
indicates we dont want to define the values for the first or third generics and they should be their default flow docsIn addition, any values which utilize the generics will be calculated so that we can
infer
based upon that. In this waywill become
{ action: 'foo', payload: { value: number } }
Use Case
So there are a ton I can come up with I can imagine with this as I have run into it a few times now running through code - but one of the main things is when I want to strictly type parameters or values but then provide helpers/utilities which may call those functions on behalf of the caller.
The problem is that we have now lost a significantly amount of type safety which we had before which essentially binds the value of
emailType
toprops
. There are many other cases where that tight coupling being maintained would be very beneficial, if more are needed I am sure I can come up with the other areas I have run into this!We would instead want
user.sendEmail('foo', { action: 'foo', payload: { value: 1 } })
to fail since it should know that we will be callingsendEmailType
withfoo
as theemailType
So even without infer in this case we could simply write the above as
Other Potential Syntax
Since there are potential issues with
typeof fn<T>
sincetypeof fn
is a type without generics, there are a few ways around that but i think the given syntax is the easiest if there is a way to bind them.as
(or another word) keyword as option when usingtypeof
on fns(typeof fn as fn<A, B, C>)
The text was updated successfully, but these errors were encountered: