Skip to content

Type narrowing fails to work in unreachable code inside false condition, resulting in spurious errors #42243

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

Closed
CurtisFenner opened this issue Jan 7, 2021 · 2 comments

Comments

@CurtisFenner
Copy link

Bug Report

TypeScript fails to apply type-narrowing inside unreachable code, which can result in errors spuriously appearing when code is temporarily made unreachable, even when "unreachable code" itself isn't an error (e.g., "allowUnreachableCode": true). My intuition is that adding extra conditions shouldn't ever make types "wider", only "narrower", and this case violates that.

I suspect that this has to do with avoiding narrowing types to never (which would result in even more type-errors). Perhaps the solution is to special-case conditions with type false to simply not participate in type-narrowing, rather than "disabling" type-narrowing on paths that have false conditions. I'm not sure if there may be other negative consequences of such a change.

I discovered this problem when I added a condition to "comment out" a block of code and an error unexpectedly appeared. VSCode does not report unreachable code as "errors" in the "Problems" pane, but does highlight the code specially and otherwise continue to provide type-checking information, so this seemed like a useful pattern for me experimenting with different implementations. However, the introduction of spurious errors adds unexpected friction.

🔎 Search Terms

type narrowing, false condition, unreachable code, warning, property does not exist on type, type checking error

🕗 Version & Regression Information

I verified that this problem occurs in all versions on the Playground (v3.3.3333, v3.5.1, v3.6.2, v3.7.5, v3.8.3, v3.9.7, v4.0.5, v4.13, and Nightly as of 7 Jan 2021)

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about unreachable code / type narrowing and did not find any entry.

⏯ Playground Link

Playground link with minimal counterexample

💻 Code

interface Alpha {
	tag: "alpha",
	alpha: number,
}

interface Beta {
	tag: "beta",
	beta: number,
}

type Either = Alpha | Beta;

function doThing(obj: Either) {
	if (false) {
		// When the above condition is replaced by "1 !== 1", there is no type error.
		if (obj.tag === "alpha") {
			// Hovering indicates that the type of `x` is inferred to be `Either`,
			// rather than `Alpha` or `never`.
			const x = obj;
			return x.alpha;
		}
	}
	return 1;
}

🙁 Actual behavior

TypeScript reports two errors:

  • Error: Unreachable code detected
    • on the body of the if (false) statement. This is expected.
  • The type of x is inferred to be Either.
  • Error: Property 'alpha' does not exist on type 'Either'. Property 'alpha' does not exist on type 'Beta'.
    • on the access x.alpha. This error vanishes if false is replaced with 1 !== 1 or some other not-statically false value

🙂 Expected behavior

TypeScript should report a single error:

  • Error: Unreachable code detected
  • The type of x should be inferred to be Alpha, rather than `Either.

I would expect objects inside the unreachable code should have their types narrowed "as normal", as though the statically false condition was not in-scope.

@MartinJohns
Copy link
Contributor

Duplicate of #26914. Used search terms: unreachable code (one of yours).

@CurtisFenner
Copy link
Author

I skimmed past that too fast and didn't notice, since it's a different type of narrowing. Thanks!

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