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

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

Closed
seansfkelley opened this issue Nov 15, 2022 · 1 comment Β· Fixed by #51545
Assignees
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue

Comments

@seansfkelley
Copy link

seansfkelley commented Nov 15, 2022

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

@ahejlsberg ahejlsberg self-assigned this Nov 16, 2022
@ahejlsberg ahejlsberg added the Bug A bug in TypeScript label Nov 16, 2022
@ahejlsberg ahejlsberg added this to the TypeScript 4.9.4 milestone Nov 16, 2022
@ahejlsberg
Copy link
Member

This is a regression caused by #51076. Putting up a PR to fix now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants