简体   繁体   中英

What's the best way to declare a TypeScript function with a discriminated union that returns the same type as its parameter?

Given this simplified vanilla JS function:

function getStringOrNumber(val) {
  if (typeof val === 'string') {
      return 'It was a string';
  } else {
      return 5;
  }
}

How can I tell TypeScript that when it gets a string it returns a string, and when it gets a number it returns a number?

I have experimented with different methods and found that using these overloads works, but it seems over-complicated and I wonder if there's something I am missing. Particularly, in this solution, I don't get why the third line is necessary (see link below for more info).

function useOverloadsExtra(val: string): string
function useOverloadsExtra(val: number): number
function useOverloadsExtra(val: string | number): string | number
function useOverloadsExtra(val: string | number): string | number {
    if (typeof val === 'string') {
        return 'It was a string';
    } else {
        return 5;
    }
}

Here are the other solutions I tried

Your overloads solution is close. The problem is on your test. In your test, you are calling the method passing the union as the parameter, but the union is not an allowed value: only string and number are. The last overload (the "implementation overload") is not part of the signature . So your test must perform the narrowing, like this:

function getValOverloads(val: string | number): string | number {
    if (typeof val === 'string')
        return useOverloads(val);
    else
        return useOverloads(val);
}

If you want to be able to pass the union (and thus receiving the union as the return value), you should add a third overload (just like you did on useOverloadsExtra ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM