39
function f(x:boolean|string) { return x }
f(true) // boolean | string

Why can't typescript understand that the return value is a boolean?

function f(x:boolean|string) {
    return typeof x === 'boolean' ? true : 'str'
}
f(true) // boolean | string

It can't understand this either.

Do I need to manually setup a function overload definition?

HDJEMAI
  • 9,436
  • 46
  • 67
  • 93
Farzher
  • 13,934
  • 21
  • 69
  • 100

1 Answers1

64

Typescript will not infer different return types based on type guards in the function. You can however define multiple function signatures for let the compiler know the links between input parameter types and result type:

function ff(x: boolean): boolean;
function ff(x: string): string;

// Implementation signature, not publicly visible
function ff(x: boolean | string): boolean | string {
    return typeof x === 'boolean' ? true : 'str'
}
HDJEMAI
  • 9,436
  • 46
  • 67
  • 93
Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357
  • actually, as far back as I can go in the playground, typescript was [capable of this](https://www.typescriptlang.org/play?ts=3.3.3#code/GYVwdgxgLglg9mABMYAKAHogXAIznAGwFMBDMAHwGcoAnGMAcwEpsoBPAByLmEUyPRQiYACaVEeQqSQB+CfmJlsianUaIA3gFgAUIn2IA9IcQABKJQC0MBmDg0iug4gdQQNJKnZcefRAF5AxABySUUwYJYZJ2cDWhAibBjYkNVg5MQAbl0AX11dYih5HADkNGCACyICAjhI7J08Ev9EeKIGptLg4IbClSEAN0SWlFRgEgJKIiYG6iIhrp7dOYWWtsygA) at least as far back as 2019. The only caveat being it doesn't have the smarts to typecheck for you within the function (and I think that's a bug), but anything calling it correctly has the right type. – Hashbrown May 20 '21 at 10:25
  • 1
    @Hashbrown you are using conditional types. 1. This answer predates conditional types . 2. I stand by the overload solution. I like conditional type but using them everywhere is overkill. – Titian Cernicova-Dragomir May 20 '21 at 11:17
  • 2
    Ah, yeah I 3.33 is as far back as playground goes, so I couldn't check as to when the question was answered. For this case overloading is perfect, that's why I didn't make an answer, 'just wanted to make sure any other readers coming for more complex reasons saw that the original question is doable in TS as-is – Hashbrown May 20 '21 at 11:46
  • Does Hashbrown example still work? I see `steve` type as string, when it dhoulg be boolean? – Quang Van Nov 03 '21 at 15:23
  • 2
    In ES6, do all signatures need to be exported via `export`? – kungfooman Nov 06 '21 at 08:01
  • 1
    @kungfooman yes, otherwise you get `Overload signatures must all be exported or non-exported. ts(2383)` – ferm10n Dec 09 '21 at 19:03
  • @TitianCernicova-Dragomir Why is it actually that "Typescript will not infer different return types based on type guards in the function" ? The problem I see with the suggested overloading approach is that in the implementation I only know that I need to return `boolean | string` - I can still return the wrong type based on the wrong condition, there is no type-safety there (whereas a conditional type could tell me if I return the correct type based on a type assertion in my code) – dwytrykus Apr 19 '23 at 08:07