Reputation: 23980
I have this generic type that I use for extracting the type of the second parameter of a function:
type SecondParam<T> = T extends (a: any, b: infer R) => any
? R
: never;
It works for most cases:
type T1 = SecondParam<(x: any, y: number) => void>; // number
type T2 = SecondParam<(x: any, y: { x: string[] }) => void>; // { x: string[] }
But when the second parameter is not present, I want it to give me void
instead of {}
:
type T3 = SecondParam<(x:any) => any> // is {}, I want void
I'm using SecondParam
to define the type of another function:
type F<T> = (p: SecondParam<T>) => void;
type F1 = F<(x: any, y: number) => any>; // (p: number) => void
type F2 = F<(x: any, y: { x: string[] }) => any>; // (p: { x: string[] }) => void
type F3 = F<(x: any) => any>; // is (p: {}}) => void, but I want () => void
But it doesn't work well for the last case, when the second parameter is missing.
Upvotes: 0
Views: 76
Reputation: 11115
The type confition (a: any, b: infer R) => any ? .. : ..
is always true because omiting paramters doesn't create compile errors see this example which compiles:
const abc: (one: string, two: string, three: string) => void = (onlyFirst: string) => { };
If you really want () => void
as type then you'd have to add a new type condition on the SecondParam type. Like this:
type SecondParam<T> = T extends (a: any, b: infer R) => any
? R
: never;
type F<T> = T extends (a: any) => any
? () => void
: (p: SecondParam<T>) => void;
type F3 = F<(x: any) => any>; // is () => void
If you want type never
which you can't really assign, then you can change the SecondParam-type like this
type SecondParam<T> = T extends (a: any) => any
? never
: T extends (a: any, b: infer R) => any
? R
: never;
// you now, can't pass the second parameter as its never:
const f: F3 = () => { };
f(); // expects 1 argument
Upvotes: 2