Support Function Type Constraints with Variable Arguments
The solution is to use the extends
keyword to constrain T
. In this case, we need T
to be typed as a function with a return type of any
:
type GetParametersAndReturnType<T extends () => any> = {}
With this change in place, we no longer have an error in our type helper, but we do
Transcript
0:00 The solution to this is to make sure that T is constraint to a certain type. The way we do that is with the extends keyword. The way we're going to do that is we're going to type it as a function. This function now, this appears to be passing up here, because we have our Parameters up here and ReturnType. Nothing's erroring up here, but we do get errors down here.
0:24 The proper way to type this is interesting. To do it, I'm going to look at the Parameters type. If I remove this constraints, then this error is giving me a detailed description of what's going on. Which is type T -- which could be unknown, remember -- does not satisfy the constraint '(...args: any) is any.'
0:46 We can come and click over to this. We can see that it has a constraint itself, T extends (...args: any) => any. If we copy over that, we'll see that this starts working now. This is the solution. Why is it the solution there?
1:01 We understand that it can return any here. If we were to specify this can only return strings, then the two things down here, which return void and a number are going to be stop moaning at us, because type 'void' is not assignable to type 'string'.
1:17 We're saying that this function here has to return a string to be valid. We can put in any here. Any says, we can accept any type of function or rather a function that returns anything, because we don't care about what it returns. We want it to be a function.
1:35 What about this section here, this ...args: any? If I remove this, as we saw before, then this says, this is what this function can accept as a Parameter. If I say, a: any here, then it's going to accept this version.
1:52 If I put in a b:any inside here too, then it's going to start accepting this version. We wanted to accept any number of arguments here, which means that we can use this rest parameter and we can say any here. It's also acceptable to do any array here. It doesn't matter.
2:08 What this does is it means that we can accept any number of arguments, including zero arguments too, and it will return a function or return anything from that function there.
2:21 By copying this constraint, we've matched up what we expect to pass into this TypeHelper based on what we want to use it as. This is a nice bit of syntax to remember, except it means, you can always use functions as constraints in your TypeHelpers.