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

Optional chaining control flow cannot narrow discriminated unions. #42120

Closed
whzx5byb opened this issue Dec 27, 2020 · 5 comments
Closed

Optional chaining control flow cannot narrow discriminated unions. #42120

whzx5byb opened this issue Dec 27, 2020 · 5 comments
Labels
Duplicate An existing issue was already created

Comments

@whzx5byb
Copy link

whzx5byb commented Dec 27, 2020

Bug Report

πŸ”Ž Search Terms

optional chaining discriminated union control flow

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried.

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

interface Position {
  x: number;
  y: number;
  computed?: never;
}

interface RelativePosition {
  x: number | string;
  y: number | string;
  computed: Position;
}

declare var pos: Position | RelativePosition;

function getComputedX(pos: Position | RelativePosition): number {
  return pos.computed?.x ?? pos.x;
  // error here. Expect to be type "number", but actually "number | string";
}

if (pos.computed?.x !== undefined) {
  pos; // Expected to be type "RelativePosition", but actually "Position | RelativePosition"
  pos.computed; 
  // Inconsistence here. 
  // If "pos" is "Position | RelativePosition", then "pos.computed" should be "Position | undefined".
  // If "pos" is "RelativePosition", then "pos.computed" should be "Position". (And this is expected.)
  // But here "pos" is "Position | RelativePosition", but "pos.computed" is "Position".
  // The inconsistence make me think it is a bug instead of a suggestion.
}

Possibly related: #34597

@andrewbranch
Copy link
Member

andrewbranch commented Dec 28, 2020

I think this is essentially a duplicate of #32399/#18758, but is notably not fixed by #38839 (it looks like maybe that’s limited to narrowing with typeof).

@andrewbranch
Copy link
Member

The original repro in #18758 can be changed very slightly to show this bug:

type A = { type: "a" }

type X = { type: A, a: string }
type Y = { type?: undefined, b: string }

declare let x: X | Y

if (x.type?.type === "a") {
	x.a // Type Error
}

@andrewbranch andrewbranch added the Duplicate An existing issue was already created label Dec 28, 2020
@ShuiRuTian
Copy link
Contributor

Interesting. I remember I try to handle expression with optional chain, but it seems I do not do it well.
However, I would have a look at this.
Thanks a lot for the case @whzx5byb and analytics @andrewbranch !

@ShuiRuTian
Copy link
Contributor

ShuiRuTian commented Jan 1, 2021

This is fixed in #38839 now!

  1. add nest QuestionQuestionToken(??) support
  2. undefined type could be narrowed correctly

@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants