Skip to content

Detection of unreachable code after call to function returning never is broken for functions exported via intermediate variable #60368

Closed as not planned
@ronjouch

Description

@ronjouch

🔎 Summary

Detection of unreachable after call to function returning never generally works.

However, it appears broken when the never-returning function is exported via an intermediate variable.

Here’s my best minimal demo:

Image

(sorry, cannot do a Playground link, as my problem is inherently multi-file, and Playground only supports one file)

🕗 Version & Regression Information

  • I noticed the bug on latest TS 5.6.3

⏯ Playground Link

Cannot share a Playground link, as Playground is single-file only, and my issue is about exports / multi-file

💻 Code

app.mjs

import {libConst} from './lib-export-const.mjs'
const {fnNeverWithConstExport} = libConst;
import {fnNeverWithEsmExport} from './lib-export-proper.mjs'

/** @returns {never} */
function fnSameModule() {
  process.exit(0);
}

function withSameModule() {
  fnSameModule();
  console.log('GOOD: properly seen as unreachable');
}

function withExport() {
  fnNeverWithEsmExport();
  console.log('GOOD: properly seen as unreachable');
}

function withConst() {
  fnNeverWithConstExport();
  console.log('BAD: incorrectly missed as unreachable');
}

// console.logs nothing (runtime behavior all good)
withSameModule();
withExport();
withConst();

lib-export-proper.mjs

/** @returns {never} */
export function fnNeverWithEsmExport() {
  process.exit(0);
}

lib-export-const.mjs

/** @returns {never} */
function fnNeverWithConstExport() {
  process.exit(0);
}

export const libConst = {
  fnNeverWithConstExport,
};

🙁 Actual behavior

TS fails to understand the never-ness of the never-returning function exported via an intermediate variable.

🙂 Expected behavior

I expect TS to understand that code following a function returning never will not run.

This is useful e.g. for early exits useful to narrow a string | undefined into a string.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions