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

Narrowing switch(true) doesnt work for default case and is wrong for fallthrough cases in 5.3 #55986

Closed
alesmenzel opened this issue Oct 4, 2023 · 6 comments Β· Fixed by #55991
Closed
Assignees
Labels
Bug A bug in TypeScript Effort: Moderate Requires experience with the TypeScript codebase, but feasible. Harder than "Effort: Casual". Fix Available A PR has been opened for this issue Help Wanted You can do this

Comments

@alesmenzel
Copy link

πŸ”Ž Search Terms

switch, fallthrough

πŸ•— Version & Regression Information

  • This is a crash No
  • This changed between versions 5.2 and 5.3

⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.3.0-dev.20231004#code/C4TwDgpgBAZg9nKBeKByAhqqAfNAjLXVAY1QCgzi4A7AZ2FmTUynVtgQtoHcBLYYgAsAFMABOAVwgBKKAG8yUJVGJtoMZEhQZUALkXLVtdZu0F9ywzVpwANhAB0tuAHNhMaQcsB6b5f9QAHoA-F7KeGIQ6ADWYQAmEDDoErbAFv5UdHaOzm4eYUq+AZYhZAC+QA

πŸ’» Code

type foo = 'a' | 'b' | 'c'

const f = 'a' as foo

switch(true) {
    case f === 'a':
    case f === 'b':
      console.log(f)
      //          ^?  'b'
      break
    default:
      console.log(f)
      //          ^?  'a' | 'b' | 'c'
}

πŸ™ Actual behavior

The fallthrough case has wrong type b.
The default case is not narrowed.

πŸ™‚ Expected behavior

In the fallthrough the type should be a union of a | b.
The default case should be c.

Additional information about the issue

Related to 70b7de1

@DanielRosenwasser
Copy link
Member

Bizarre that it might have something to do with empty case clauses

Playground Link

type foo = 'a' | 'b' | 'c'

const f: foo = 'a' as any

switch(true) {
    case f === 'a':
      console.log(f)
      //          ^? "a"
      // falls through 
    case f === 'b':
      console.log(f)
      //          ^? "a" | "b"
      break
    default:
      console.log(f)
      //          ^? foo
}

@DanielRosenwasser DanielRosenwasser added the Bug A bug in TypeScript label Oct 5, 2023
@DanielRosenwasser DanielRosenwasser added this to the TypeScript 5.3.1 milestone Oct 5, 2023
@DanielRosenwasser DanielRosenwasser added Help Wanted You can do this Effort: Moderate Requires experience with the TypeScript codebase, but feasible. Harder than "Effort: Casual". labels Oct 5, 2023
@jakebailey
Copy link
Member

@Andarist if he beats me to it before tomorrow

@fatcerberus
Copy link

@DanielRosenwasser fwiw while your code narrows correctly for the cases, it still gets default wrong (it should narrow to "c")

Also when did switch (true) start working? (this pattern is an irrational pet peeve of mine but that's neither here nor there)

@DanielRosenwasser
Copy link
Member

I also think it's a little hokey but #53681

@jakebailey
Copy link
Member

This comes down to the fact that the PR didn't handle multiple clauses at all... I should have known the PR was too simple πŸ˜…

I have a fix for the multiple clause cases, but default, not so sure about. May need to just be unnarrowed there as I'm not sure we have a mechanism to narrow like we do the other switch case instances as those do the narrowing directly without control flow, whereas this has to be more like if statements or something. I guess we'll have something like this eventually for matching...

@jakebailey
Copy link
Member

PR at #55991.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Effort: Moderate Requires experience with the TypeScript codebase, but feasible. Harder than "Effort: Casual". Fix Available A PR has been opened for this issue Help Wanted You can do this
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants