Home > Back-end >  return type of function based on argument value existence in TypeScript
return type of function based on argument value existence in TypeScript

Time:01-14

I have the following function in index.js file:

function myFn(val) {
  if (val) {
    return val;
  }
  return console.log(val);
}

I have the following type declaration in index.d.ts file:

declare function myFn<T>: (val?: T) => (T | void);

But the problem is that if i pass no arguemnt then there is no case where the function can return any value other than void type.

I would like to do something like this:

declare function myFn<T>: (val?: T) => (val ? T : void);

How can i implement this best? any ideas?

CodePudding user response:

You can use function overloads to determine the return type of a function based on the arguments passed to it. For example:

function myFn<T>(): void
function myFn<T>(val: T): T
function myFn<T>(val?: T): T | void {
  if (val) {
    return val;
  }
  return console.log(val);
}

TypeScript Playground

CodePudding user response:

That's not valid syntax, but I am going to assume you meant this:

declare function myFn<T>(val?: T): (T | void);

The problem here is that val is absent, the type T is not knowable, so typescript infers it as unknown.

To fix it, you need to give your generic parameter a default value for the case when there is no argument. Now typescript knows exactly what to use when val is omitted and doesn't have to guess.

declare function myFn<T = void>(val?: T): T;

const iAmVoid: void = myFn()
const iAmString: string = myFn('a string')

Playground

CodePudding user response:

@Alex 's answer is correct, I was just writting these examples that shows the way to use generics in different ways to avoid messing up the return type:

declare function myFn<T=void>(val?:T ):T  ;
const tvoid = myFn() // <-- type is void 
const tsds = myFn("sds") // <-- type is "sds" and not string
const tstring:string = myFn("sds") // <-- type is string  
const tstring2 = myFn<string>("sds") // <-- type is string  
const tnumber = myFn<number>(3) // <-- type is number
const t3 = myFn(3) // <-- type is 3

AFAIC, I prefer const tstring2 = myFn<string>("sds") that I find more "elegant"

  •  Tags:  
  • Related