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

Implement Discriminated Unions #149

Merged
merged 2 commits into from
Jun 22, 2020
Merged

Conversation

ivank
Copy link
Contributor

@ivank ivank commented Jun 5, 2020

First of all, AWESOME library! One thing has been bugging me about it though and its support for Discriminated Unions.

This is my attempt on addressing it, and I've seen similar issues being raised too.

So with this PR, when those conditions are met:

  • all the alternatives of a union are records
  • they have at least one field in common, that is a literal in each
    record with unique values

Then when checking the alternatives we can pick the correct one first, and then perform the validation, thus producing more specific error messages.

This is something already present in TypeScript itself https://www.typescriptlang.org/docs/handbook/advanced-types.html#discriminated-unions and seems to have been requested before #67 .
Though this implementation would not work in all the cases covered by TS, but it's a start.

I'll be glad to add more tests or work on the implementation on your direction. Sorry for the long implementation, but the you seem to be supporting way older version of JS than I'm used to so had to implement the logic in for loops and such.

If:
- all the alternatives of a union are records
- they have at least one field in common, that is a literal in each
record with unique values

Then when checking the alternatives we can pick the correct one first,
and then perform the validation, thus producing more specific error
messages.

This is something already present in TypeScript itself https://www.typescriptlang.org/docs/handbook/advanced-types.html#discriminated-unions
Though this implementation would not work in all the cases covered by
TS, but its a start.
@coveralls
Copy link
Collaborator

coveralls commented Jun 5, 2020

Coverage Status

Coverage decreased (-0.1%) to 99.127% when pulling fae476a on ivank:discriminated-unions into ea72974 on pelotom:master.

@@ -966,6 +968,46 @@ export function Union(...alternatives: Rt[]): any {

return create(
(value, visited) => {
if (
alternatives.length > 1 &&
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this condition necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn’t call it necessary, just a performance optimization that we can easily get rid off. If you think its not worth it I can remove it for sure. It might help with coverage as well.

Also we can implement some of the checks with type guards and that would help with coverage as well, but I figured I’d use existing types as much as possible. The current way Reflect is implemented I can’t see a way to reuse the types for typeguards.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think for simplicity's sake we should remove it.

@kael-shipman
Copy link

Hey all! Very interested in seeing this come through :). This is a godsend library, and I love to see it improving like this.

@pelotom pelotom merged commit c905806 into runtypes:master Jun 22, 2020
@ivank ivank deleted the discriminated-unions branch June 29, 2020 07:09
@yuhr yuhr mentioned this pull request Mar 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants