I have the following objects:
const object1 = {
foo(a?: any) {}
}
const object2 = {
foo(a: any) {}
}
Is there any way to know whether the parameter passed to the foo function is optional?
I only know how to get if it doesn’t have params:
type NoParams = Parameters<typeof object['foo']> extends [] ? true : false
>Solution :
The algorithm:
- Write a type that accepts a generic parameter constrained by any function
- Store parameters of the function in the inferred parameter constrained by
unknown[]
Params
- Call recursive type
Traverse
and passParams
to it to check the parameters one by one:- If the array is empty return true
- Retrieve the first element from the array
- If the first element extends its required version (without optionality) it means that the element itself is not optional:
- Return false;
- Else:
- Call the
Traverse
for the rest of theParams
.
- Call the
Implementation:
We are going to use infer keyword, which will allow us to store the parameters in a separate parameter and retrieve elements from the array.
type Traverse<T extends unknown[]> = T extends [
infer First,
...infer Rest extends unknown[]
]
? First extends Required<First>
? false
: Traverse<Rest>
: true;
type HasNoRequiredParams<T extends (...args: any[]) => any> =
Parameters<T> extends infer Params extends unknown[]
? Traverse<Params>
: never;
Testing:
// true
type Case1 = HasNoRequiredParams<(arg?: string) => void>;
// false
type Case2 = HasNoRequiredParams<(arg: string) => void>;