-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Description
🔎 Search Terms
"Function lacks ending return statement and return type does not include 'undefined'."
"Not all code paths return a value."
🕗 Version & Regression Information
I have searched the FAQ and issues on GitHub, but couldn't find this question. I have seen similar things, but the arguments for the behavior in those doesn't apply in this case. I tried tried the latest and oldest versions of TS in the playground, and the issue was always there.
In other similar issues, there always seems to be a way to send in more than expected. For example, in #13215 it's about a generic function that can receive something else because of the "extends" keyword.
In #36884 it's because "instanceof" is open ended so to speak.
In my case, I'm talking about a closed set of primitives. In case it's just that I haven't been able to find the duplicates of this one, I'm sorry.
⏯ Playground Link
💻 Code
type ArgType = `foo` | `bar`;
const testFunction = (arg: ArgType): string => {
if (arg === `foo`) {
return `Arg is foo`;
}
if (arg === `bar`) {
return `Arg is bar`;
}
// Here, arg is of type never
};
const callerFunction = (first: ArgType | `baz`, second: string, third: any) => {
testFunction(first); // Error!
// Argument of type 'ArgType | "baz"' is not assignable to parameter of type 'ArgType'.
// Type '"baz"' is not assignable to type 'ArgType'.
testFunction(second); // Error!
testFunction(undefined); // Error!
testFunction(); // Error!
testFunction(third) // Only one that works, but then you have basically just turned off type checking, so this
// should not count as a counter example.
};🙁 Actual behavior
The testFunction doesn't compile, returns "Function lacks ending return statement and return type does not include 'undefined'." error.
🙂 Expected behavior
testFunction should compile without errors.
Additional information about the issue
I run into this quite often in Angular with computed signals. If I add an ending return statement, it's wrong for several reasons.
- It implies the function can return whatever value I would put in the end, which is not true.
- Overall, it bloats the code, and unreachable code is not exactly best practice.
- Most critically, the reason this is a more serious problem. If ArgType is expanded to
'foo' | 'bar' | 'baz', then there SHOULD be an error. If I have a return statement in the end, that's just hiding the error and I could just as well use // @ts-ignore.