Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

never return type not respected on function called on object with inferred type #58704

Closed
nwalters512 opened this issue May 29, 2024 · 2 comments

Comments

@nwalters512
Copy link

nwalters512 commented May 29, 2024

🔎 Search Terms

"return never type inference", "return never control flow"

I came across #12825, but the code snippet there works as expected, and I have something similar working as expected in my reproduction.

I also saw #34955, but it's not clear to me if it's related to my issue or not (it seems separate).

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about

⏯ Playground Link

https://www.typescriptlang.org/play/?#code/JYOwLgpgTgZghgYwgAgDIHsDmnrIN4BQyyEAHkgA5jDogAUAtgM6YBcyTYUomAlOyAgA3aAG4CAXwIEYAVxAJqtEqQgJZkAFLoARnQBWu9nSFwANu07cQmANoBdZAB9kIWWbMAaZGaw4o7BjY0LzIALwAfMhC6MAAJqGExAi0nD5+0IEZUOH4RMQqlEr0zGwcXDyJ+QXIYAAWUOgA7q4QLQCiUI1QjCy84jUSnvkS4vmGem4e3r7BUP2S0mRqGhDaeibmM9mhkXnEwDDIdACEAIJdcACeAHTATBdQ15tmvFU1s-43ZEU09ADkkE4PH+C2IUnyKRATHQZggN1mLzuIDiZAA8jA6ICIMCbKCFhIFgRluotLo6C9tnMsnNdlEkshDsdzpdbvdHs9TK93gVPtBvuQIFQ-ligdQ8WDkBDkqlYfDEVzkajSBjRTjxZh8eJCeIgA

💻 Code

interface Logger {
  exception(msg: string): never;
}

function executeJob(job: (val: string[] | null, logger: Logger) => void) {
  const logger: Logger = {
    exception(msg: string) {
      throw new Error(msg);
    },
  };

  job(null, logger);
}

executeJob((val, logger) => {
  if (!Array.isArray(val)) {
    logger.exception('testing');
  }

  console.log(val.indexOf('testing'));
});

executeJob((val, logger: Logger) => {
  if (!Array.isArray(val)) {
    logger.exception('testing');
  }

  console.log(val.indexOf('testing'));
});

The example is kind of contrived, but it's a very simplified version of something from a real-world codebase. I jumped through hoops to get it to clearly show an error in the failing case.

🙁 Actual behavior

When the "job" function has the type of logger inferred as below, reachability/control flow analysis incorrectly determines that val could be of type null on the console.log(...) line:

executeJob((val, logger) => {
  if (!Array.isArray(val)) {
    logger.exception('testing');
  }

  console.log(val.indexOf('testing')); // 'val' is possibly 'null'. (18047)
});

However, when the type of Logger is explicitly annotated, things work as expected and the type of val is correctly narrowed to string[] after logger.exception(...) is called.

executeJob((val, logger: Logger) => {
  if (!Array.isArray(val)) {
    logger.exception('testing');
  }

  console.log(val.indexOf('testing')); // no error, as expected
});

🙂 Expected behavior

I would expect the first example above with an implicit type for logger to behave the same as when the type of logger is explicitly declared to be Logger.

Additional information about the issue

No response

@IllusionMH
Copy link
Contributor

More like #55154 and linked issues.
As you've noticed it needs explicit annotation.

@nwalters512
Copy link
Author

Good find! That didn't show up in my search. I'll close this as a duplicate, though it's a shame this can't be made to work.

This should probably make its way into the FAQ? From the "many many others" comment in the issue you linked, it sounds like this comes up regularly.

@nwalters512 nwalters512 closed this as not planned Won't fix, can't repro, duplicate, stale May 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants