Reputation: 798
enum Test {
one,
two,
}
const play = (n: Test) => {
switch (n) {
case Test.one:
return 'hello';
case Test.two:
return {};
default:
exhaustive(n);
throw new Error('hi');
}
};
const b = play(Test.one);
//
console.log(b);
Can someone help me understand why Typescript can't infer that the return type of play(Test.one)
is a string instead of an object? Also, if there's something I can do to make it work, I would love to know that as well.
Typescript 3.9.4
Hovering over the typeof b yields:
Upvotes: 3
Views: 621
Reputation: 250106
Typescript will not try to infer anything like this accurately (basically infer overloads based on the switch statements). The best you can hope for from TS inference is a union of all possible return types. In your case you get the return type as {}
because most types are compatible with {}
, even string
so the union {} | string
simplifies to {}
.
Your only solution here is to be explicit about the return types using multiple overloads (although you will need a function declaration, overloads can't be defined on a function expression):
function play(n: Test.one): "hello"
function play(n: Test.two): {}
function play(n: Test) {
switch (n) {
case Test.one:
return 'hello';
case Test.two:
return {};
default:
exhaustive(n);
throw new Error('hi');
}
};
const b = play(Test.one); // "hello"
Note: Your implementation will not be checked against the overloads, so it's up to you to ensure that implementation and overloads agree.
Upvotes: 1
Reputation: 898
The reason is that every return value has a different type one returns a string one returns an object and one an error. This way linter will choose the base class which is object
Upvotes: 1