Is it possible to make return type of function dependent on the argument type?
const exampleFunction<T> = (initial?: T, ...anotherArgs) => { ...Some logic }
In this example by default we can use T | undefined, but I need that return type of function always be T if initial data is defined and (T | undefined) if it is undefined
CodePudding user response:
Is it possible to make return type of function dependent on the argument type?
This question in a general sense is typically answered by function overloads.
In this case you could do something like:
function exampleFunction<T>(initial: T): T // overload 1
function exampleFunction(initial?: undefined): undefined // overload 2
// Implementation
function exampleFunction<T>(initial?: T): T | undefined {
return initial
}
const a: { abc: number } = exampleFunction({ abc: 123 }) // use overload 1
const b: undefined = exampleFunction() // use overload 2
const c: undefined = exampleFunction(undefined) // use overload 2
However, reading your question more carefully...
always be T if initial data is defined and (T | undefined) if it is undefined
You can change the second overload to:
function exampleFunction<T>(initial?: undefined): T | undefined // overload 2
But that will require a manual type for T
since none can be inferred.
const b: { def: string } | undefined = exampleFunction<{ def: string }>() // use overload 2
CodePudding user response:
You can use a function which simply extracts the first element type from rest parameters.
- If no arguments are provided, the return type will be
undefined
because the first argument's type is (implicitly)undefined
- If the first argument is
T | undefined
, so will be the return type - If the first argument type is
T
, so will be the return type
function typeOfFirstArgument <Args extends readonly any[]>(...args: Args): Args[0] {
const [first] = args;
// ...
return first;
}
const result1 = typeOfFirstArgument(); // undefined
const result2 = typeOfFirstArgument('ok', 'another'); // string
const result3 = typeOfFirstArgument(...['ok', 'another'] as const); // "ok"
const result4 = typeOfFirstArgument({ msg: 'hello world' }, ['foo', 'bar']); // { msg: string }
let value: string | undefined;
const result5 = typeOfFirstArgument(value); // string | undefined