Closed OliverJAsh closed 2 years ago
tsc is narrowing the type of the object property in the outer switch case when we don't want it to:
type A = 'a1' | 'a2'
declare const x: { y: A }
switch (x.y) {
case 'a1': { // narrows
switch (x.y) {
case 'a2': {} // errors
}
}
}
We can't do something like as typeof x.y
as that's similarly impacted by this narrowing.
Is it semantically viable to unflatten the AST? That'd workaround this issue and give terser output, and it'd avoid having to concern the JS compiler with a fundamentally TS issue.
Is it semantically viable to unflatten the AST?
I have no idea. 😬
Here's a hacky way we could solve this. Change all switch conditions from x.y
to (() => x.y)()
(or id(x.y)
- all that matters is that it enters a function which TS won't follow). :laughing:
Alternatively we could try to keep track of what we've matched upon so far but... I'm a fan of how we've avoided essentially doing our own typechecking until now.
One other way to solve this might be to use a type assertion everywhere we use switch
, to undo any narrowing from the parent scope.
type A = 'a1' | 'a2'
declare const x: { y: A }
switch (x.y as A) {
case 'a1': { // narrows
switch (x.y as A) {
case 'a2': {} // no error
}
}
}
(I suggested doing it for all switch
es so we don't have to keep track of which ones are nested.)
Also, we don't have to solve this if there's no elegant solution. I don't think it's going to come up very often.
Given this JSON:
app/routes/Users/components/UserStatsSubRoute/components/StatsGraph/lang/en-US.translations.json
:If we compile, it generates valid TS:
However, if we flatten and then compile, the generated TS has a type error: