-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Discriminated Unions - Multiple Fields, SubClassing/interfacings, kind field detection failure #27541
Comments
Forcing a user to always define a discriminator field has a runtime cost. It's possible to avoid needing a discriminator by analyzing the field/type combinations of each union member and building an efficient "given this object which union member are you?" query. It's definitely non-trivial but handles currently "surprising" cases like this I'd rather have the compiler figure out the more efficient way to automatically discriminate types (and maybe warn if a type in a union is unable to be discriminated) than give the user a way to signal the discriminator. |
This issue is a bit hard to get into, maybe it could be written to gently get into the more deep issues? Am I correct in assuming that the root of many of these failures is simply described as the following? type T1 = { a: number, b: number }
type T2 = { a: number, c: number }
type U = T1 | T2
const x: U = { a: 1, b: 2, c: 3 } // Does not implement either of the union'ed types! In the above And for a more concrete use case: Imagine specifying an options object for a function (so it generally cannot have any literal values to use for discriminating the types) that must include one of two options, but never both. I haven't figured out a way to do this. |
@blixt Typescript terminology use sets and logic is not as clear as you would think, but too late to change now fix now, because everything would break. You will just have to learn to work around the corner cases. For what you want the following would work, which not discriminator types logic really, it is mix in different Record shapes into one larger one. type T1 = { a: number, b: number }
type T2 = { a: number, c: number }
type U = T1 & T2 // Note that anding types would work here.
const x: U = { a: 1, b: 2, c: 3 } |
@wesleyolis That's even further away from what I would want, because it creates a new type with |
There's a few different ways to think about these operations: Operators as bitwise ops and types as Rows: Operators as logical and types as validators: Honestly I'd like both of these AND have types closed by default (otherwise unions are pretty silly). I'd say In the end (probably including things outside the scope of this bug), I'd love to be able to describe types like these:
|
TypeScript Version: [email protected]
Search Terms:
Discriminated Unions - Multiple Fields
Issues:
When there are multiple common fields between interfaces the Discriminated Unions is not able to determine which field is to be the discriminator and all the logic that typescript will constrain the shape of the function interfaces bases on a field, check will not work.
It would be great if we could in cases like these define a common interface on which there is a single field present from which all other instance inherited from that shape. Then when one defines a union of types, if it can't find a single common field, then it inspects the base interfaces for an interface with a single field, if found, it will use that field from that interface. Seem to be present with many cases, were I need to communicate to typescript which field should be used.
There would still be a problem, if there is common class from which all inherited that only has a single field, in which case another form of syntax would be required when defined the discriminant, like including the common interface in the discriminate. This method, might be the preferable option, because it would be more performance than inspective all the interfaces form which a class extends from. I would choose this form, because simpler, as know exactly what to inspect at a top level.
See examples below of all the cases.
type Kinds = KindA | KindB | Kind
An improvement, would be to allow instanceof and similar variants to be used, versus string literals.
The text was updated successfully, but these errors were encountered: