'Create dynamic optional parameter for inferred generic
I have an object that is shaped like this:
{
first: (state: S, payload: boolean) => { payload: boolean, type: string },
second: (state: S) => { payload: undefined, type: string },
}
And I'm generating an object where the state property is taken out. So it looks like this:
{
first: (payload: boolean) => { payload: boolean, type: string },
second: () => { payload: undefined, type: string },
}
The returned object is typed like this:
{ [K in keyof T]: { (payload: Parameters<T[K]>[1]): { payload: Parameters<T[K]>[1]; type: K; }; name: K; } }
Where Parameters<T[K]>[1] can clearly be undefined (as in the second case above).
This mostly works fine. I get the correct type inference of the function names, the parameters, and the return types, EXCEPT if the payload is undefined. It still wants me to specify it. For example:
first(true); // works, no errors
first('true'); // fails because it's the wrong type. Excellent
second(undefined) // works, no errors
second(); // errors
The error is:
(property) second: (payload: undefined) => {
payload: undefined;
type: "second";
}
Expected 1 arguments, but got 0. [ts(2554)]
So the question is how can I make this optional, but only when the payload is not provided? If I add (payload?: Parameters<T[K]>[1]) in the return type then all the functions have this property as optional, and if I add (payload: Parameters<T[K]>[1] | undefined) - I still get the same result as before.
Solution 1:[1]
The answer was to create a conditional function declaration in the return type, like this:
{ [K in keyof T]: Parameters<T[K]>[1] extends undefined ?
{ (): { payload: Parameters<T[K]>[1]; type: K; }; name: K; } :
{ (payload: Parameters<T[K]>[1]): { payload: Parameters<T[K]>[1]; type: K; }; name: K; }
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
