Reputation: 1801
i want to know wheather function's first args is optional, so i write this:
type F1 = (payload?: number) => null;
type Res1 = F1 extends (a?: any) => any ? 1 : 2; // got 1
type Res2 = F1 extends (a: any) => any ? 1 : 2; // got 1, but 2 expected
type F2 = (payload: number) => null;
type Res3 = F2 extends (a?: any) => any ? 1 : 2; // got 1, but 2 expected
type Res4 = F2 extends (a: any) => any ? 1 : 2; // got 1
ALL OF THEM are both equl to 1
, why ? and how do i do ?
Upvotes: 0
Views: 131
Reputation: 4010
You can read 'extends' as 'is assignable to'.
type F1 = (payload?: number) => null;
type Res2 = F1 extends (a: any) => any ? 1 : 2; // got 1, but 2 expected
Is (payload?: number) => null
assignable to (a: any) => any
? Let's check:
// Works
const res2: (a: any) => any = (payload?: number) => null;
(a: any) => any
accepts any value for a
, including undefined or a number as specified by payload, so we can see that (payload?: number) => null
is assignable and therefore F1 extends (a: any) => any
should evaluate to true and return 1.
Instead, you can make the arguments of your function to test optional using Partial, and check if the resulting arguments are assignable to the original arguments:
type ArgumentType<F extends (...args: any) => any> = F extends (...args: infer A) => any ? A : never;
type FirstArgumentOptional<F extends (...args: any) => any> =
Partial<ArgumentType<F>> extends ArgumentType<F>
? true
: false
type T1 = FirstArgumentOptional<(a: any) => any>; // false
type T2 = FirstArgumentOptional<(a?: any) => any>; // true
type T3 = FirstArgumentOptional<() => any>; // true
Upvotes: 1