Skip to content

[4.9.2-rc regression] if/else narrowing with a branded string discriminant no longer eliminates matched constituents in later branchesΒ #51538

@seansfkelley

Description

@seansfkelley

Bug Report

πŸ”Ž Search Terms

assert never branded string literal union type narrowing

πŸ•— Version & Regression Information

This changed between versions 4.8.4 and 4.9.2-rc

⏯ Playground Link

Playground link

πŸ’» Code

type Left = 'left';
type Right = 'right' & { right: 'right' };
type Either = Left | Right;

function assertNever(v: never): never {
  throw new Error('never');
}

declare const value: Either;

if (value === 'left') {
  const foo: 'left' = value;
} else if (value === 'right') {
  const bar: 'right' = value; // correctly narrowed despite branding...
} else {
  assertNever(value); // ...but not eliminated as a candidate
}
Output
"use strict";
function assertNever(v) {
    throw new Error('never');
}
if (value === 'left') {
    const foo = value;
}
else if (value === 'right') {
    const bar = value; // correctly narrowed despite branding...
}
else {
    assertNever(value); // ...but not eliminated as a candidate
}
Compiler Options
{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true,
    "strictBindCallApply": true,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "alwaysStrict": true,
    "esModuleInterop": true,
    "declaration": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "target": "ES2017",
    "jsx": "react",
    "module": "ESNext",
    "moduleResolution": "node"
  }
}

πŸ™ Actual behavior

The compiler claims the assertNever is reachable (by virtue of only narrowing value to Right in the last branch).

πŸ™‚ Expected behavior

The assertNever is considered unreachable (that is, value is narrowed to never).

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions