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

Union of generic variants #43

Open
Stouffi opened this issue May 24, 2018 · 10 comments
Open

Union of generic variants #43

Stouffi opened this issue May 24, 2018 · 10 comments

Comments

@Stouffi
Copy link

Stouffi commented May 24, 2018

It would be great if unionize could support union of generic variants

I'm using a generic interface in one of my projects to represent generic fetch status

export interface Fetch<T> {
  results: T[]
  finished: boolean
}

and I want it to become

export interface FetchLoading {
  type: 'loading'
}

export interface FetchSuccess<T> {
  type: 'success'
  results: T[]
  finished: boolean
}

export interface FetchSuccessWithErrors<T> {
  type: 'successWithErrors'
  results: T[]
  finished: boolean
  errors: string[]
}

export interface FetchError {
  type: 'error'
  reason: string
}

And I would create an union type which could be consumed by a UI component showing the fetch status according to its type.

How could we achieve that with unionize?

@pelotom
Copy link
Owner

pelotom commented May 24, 2018

This was discussed in #4 but never realized. I don’t have time at the moment to pursue it but PRs are welcome.

@OliverJAsh
Copy link
Collaborator

Do you have any ideas what changes are necessary to make this possible, or if it is even possible?

@OliverJAsh
Copy link
Collaborator

In the absence of support for generics, I'm having to create the tagged union types, constructors, predicates et al. manually. In case it helps anyone else, here is an example: https://gist.github.com/OliverJAsh/9619a49d345c334e5f68473565457167

@pelotom
Copy link
Owner

pelotom commented Sep 16, 2018

See my comment on #4... it seems like TypeScript needs generic value types for this to be practical.

@twop
Copy link
Contributor

twop commented Nov 19, 2018

Hey, I was thinking on that problem a lot and finally shipped a version that Im comfortable with: https://github.com/twop/ts-union

const Maybe = Union(val => ({
  Nothing: of<void>(),
  Just: of(val)
}));

const {Nothing, Just} = Maybe;

Just(1); // MaybeVal<number>
Just('str'); // MaybeVal<string>
Nothing<boolean>(); // MaybeVal<boolean>

Conceptually I have a special token type Generic and I replace it with an actual type like string at the moment of construction.

type CreatorFuncG<K, Rec> = K extends Of<infer A>
   ...
    ? A extends [Generic] 
    ? <P>(val: P) => UnionValG<P, Rec> : never
   ...
: never;

Might be applicable to unionize as well :)

@OliverJAsh
Copy link
Collaborator

@pelotom Do you think we could work something like what ts-union has into Unionize?

@pelotom
Copy link
Owner

pelotom commented Oct 18, 2019

@OliverJAsh I don't have time to work on it myself, but I'm all for it!

@pelotom
Copy link
Owner

pelotom commented Oct 18, 2019

@twop any interest in porting your idea into unionize?

@twop
Copy link
Contributor

twop commented Oct 18, 2019

That would be quite a challenge (unionize types a bit more complex), but might be a fun one too :)

What about API?

// port from ts-union
const Maybe = unionize(a => ({
  Nothing: {},
  Just: ofType(a) //   'Just: a' might be more ergonomic
}),
{value: "val"}); // this is probably required because not every 'a' could be spread

I don't have time within the next couple of weeks but happy to try after that

@pelotom
Copy link
Owner

pelotom commented Oct 18, 2019

  Just: ofType(a) //   'Just: a' might be more ergonomic

Yeah, I don't see any reason to make it more verbose than it has to be.

{value: "val"}); // this is probably required because not every 'a' could be spread

Hmm, yeah, I wonder if we want to enforce that they pass a value property or just treat it as implied.

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

No branches or pull requests

4 participants