-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Repeated in
checks of asserted/predicate-d type don't work
#61526
Comments
AI explanation of this, which is correct: The key point is that although you start with the union type In the In the else branch: After the if/else block: In other words, once you combine the branches, the extra properties that distinguish One, Two, and Three are βlostβ because the only common structure across both branches is what is defined in Base. That's why the final type of some is inferred as Base. This behavior highlights how TypeScriptβs control flow analysis and union simplification work when the union members share a common base type. There's not an obvious way to fix this without breaking other invariants, but folks are welcome to try |
I didn't emphasize this as much as I could've, but there are no |
There's still an implicit join point in the control flow graph, since the body of the |
This only seems to happen when the type comes from an |
To clarify:
Shouldn't they all be the same, or if it has to do with control-flow branching, shouldn't the first two and last two be the same? |
Different code doing different things is not per se unexpected. |
The different behavior isn't contingent on whether you use |
π Search Terms
in, union, assertion, predicate, interface
π Version & Regression Information
This is the behavior in every version I tried, and I reviewed the FAQ for entries about common misconceptions regarding
{}
and propertiesβ― Playground Link
https://www.typescriptlang.org/play/?ts=5.9.0-dev.20250403#code/JYOwLgpgTgZghgYwgAgEJwM4oN4ChnIYAWcUEAJgPoAOUA9tdGAJ4BchYUoA5gNy4BfXKEixEKALJ0MYADbMAogFtqLZBAAekEOQxpMOISOjwkyAPIgUm7bv1ZkeAnSvsZXEH0HDwJ8cgAVAHc6dS0IHT10BydkMBC3Th5+I18xMwCiMmtwyPscfDisiAhEjy8hFkZkAGU6JRQAXmQpGXllVWZkAB8LKx7AkIHM7P4YAFcQBDBgF2RMLCgwSgx6iAAKVYb2SYBrEDogkABKdgWmPS2UYD06hschCamZuZuVtc21nZB9w5O3NbIG61QGxMhgcZQEBxKDjCApXAIFwyQhfZB7A5HZDNbACfjCGDIdZvK6fBrHY6OQoAempyDou0KACIXBAmUDoVdkAAybmohoAOlZAtkEW4YCI-AITPidHZoH5KF5ioFspFYolUuQMpC8s5gOVV1VIXVnk1uBpdOg9CghWAhPWLKsesVlKNwtFZsldodTrZHNdKo9GslyFpyAA5O6rBGgXo6ISqigIxi-hGBT6iTq5QGrm61sa6KbxaHw1GC7LY8CE3FmNUUz9MSB095cOclu8GmSIMd+OGGbg-S6uYaC8Gvfxs8ODXyjWrPSXJ7Lp-dR4L5yG+1aoDaCVnWSue0GrMXzfb987c2t84Lx4uw3Ty7eY3H6Ym68nU0cW+fHcur+SKobhOD6RnOIRVvG771l+zYZkAA
π» Code
π Actual behavior
Types don't get inferred past the first branch.
π Expected behavior
All branches should infer the type.
Additional information about the issue
I'm implementing JSON Type Definition types, and I'm running into some problems
with type narrowing. A JTD schema can be empty (except for common
metadata
andnullable
properties) or it can take a form based on its keys. When using atype predicate to check something fits a general schema type, weird things
happen when i use the
in
operator to check for the presence of keys. If it hasa "type" property, it's the type form, if it has a "values" property, it's the
values form, so on. I'm checking for the presence of "properties" or
"optionalProperties" which works fine for the first check, but subsequent
unrelated branches assume that the type is impossible, and it's gotta be one of
the other union members. This only happens with
if
, not with conditionalexpressions. here's the original code:
I made it work by using
Record<string, none> & Shared
for the empty form, butthat doesn't feel right (and type inference is messed up in a different but
non-erroring way).
The text was updated successfully, but these errors were encountered: