Skip to content

Return statement required even when not needed #63264

@eliashakuni

Description

@eliashakuni

🔎 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

https://www.typescriptlang.org/play/?#code/ATAuE8AcFNgQQE4HMAqVYF5gAMBmB7fbYAHxwCMBDBbAbgCh6QBjfAOwGdQxouAxAK5tmoAJbtgWABTUkALnjI0MAJQKuCUWySSAfMADeTEMFG5gM5JIxY8hbCsPGTwBNFACEbHIh2iOwAREDC4AvowuZhay1rZUNI5GLiBuHl4+Vv7A8XTOwOF5APSFwAAS0G4ANMAxWfjmEDDAbNAAbhXGoQzGrJzczJQANoMVgsJiEtK4oghcCr7KsGTYVABe2NUc0L0AJuqgmtrVoAAWM3s1bOCOGPpJJqC8oGMi4mxS07OgKrTAxcAAUQQCHwCAAhEUSr4BABbaBsbj1MDoYAAcgWKLIACI1ljUaYAmx8NxKBwOKIkGxKOQRmB8MBINRKHDHghgEjGrB0Up0KiAHSQ4CLNE4yirPEE5rEmpkilUmmwUD0zlojEwfl5PKPfhCV7sKRbXY-P4lIEg8Fap4vCbvIQ7aDTFo7Y3-M2giEubXPXU2qQu03A90RB5Wn1vKSnc6Of4AeTYg3A7JaYBOlG4AHdQQBrDjVcgCbineHAcD4ATAVPtbKk0QDYaJgBWAi4YE8TvZuAaKOYJ22Wa0SE2yrOAQ4JzLgx2Uv6ZYRMpqwFYQlZwGgAA9mZARgKQF1GPQgA

💻 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.

  1. It implies the function can return whatever value I would put in the end, which is not true.
  2. Overall, it bloats the code, and unreachable code is not exactly best practice.
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions