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

Generic variant usage with function as payload #13

Open
ohana54 opened this issue Feb 21, 2021 · 3 comments
Open

Generic variant usage with function as payload #13

ohana54 opened this issue Feb 21, 2021 · 3 comments

Comments

@ohana54
Copy link

ohana54 commented Feb 21, 2021

Hi again :)

I'm trying to create a generic variant:

const [Matcher, __Matcher] = genericVariant(({ T }) => ({
  Specific: payload(T),
  Custom: (payload: (v: typeof T) => boolean) => ({ payload }),
}))
type Matcher<T, TType extends GTypeNames<typeof __Matcher> = undefined> = GVariantOf<typeof __Matcher, TType, { T: T }>

Specific is pretty straight-forward, where Custom accepts a function that needs to use the generic type.

When using Specific in a "wrong" way, I get an expected error:

// error due to `number` payload not matching `string`
const matcher: Matcher<string> = Matcher.Specific(5)

When using Custom in a "wrong" way, I don't get an error:

const matcher: Matcher<string> = Matcher.Custom((v: number) => v === 1)

I'm probably doing something wrong with the variant creation, how can I get the generic type of Custom to work?

Thanks!

@paarthenon
Copy link
Owner

Hey I haven't looked into this yet but it's more likely it's my fault than yours. Generic variants are... hard. I probably overlooked a case. I'll see what I can do.

@paarthenon
Copy link
Owner

Hello @ohana54. I've finally found freedom from professional obligations (say that five times fast). I've been taking some creative license and rewriting most of the library for variant 3.0. As part of that, I tackled generics. There's a new interface I hope you'll find satisfactory. I've ported your example to use it.

As a brief reminder, Variant 3.0 changes the purpose of the variant() function to be a catch-all creation tool. The function to create a single case is now called variation(). You can see the full list of changes in Issue #17 .

const Matcher = variant(onTerms(({T}) => ({
    Specific: payload(T),
    Custom: (payload: (v: typeof T) => boolean) => ({payload}),
})))
type Matcher<T, TType extends TypeNames<typeof Matcher> = undefined> = GVariantOf<typeof Matcher, TType, {T: T}>;

Note you no longer need a __Matcher variable.

With these changes (and executing on TS 4.2.4) I receive an error when using Custom in a "wrong" way.

const matcher: Matcher<string> = Matcher.Custom((v: number) => v === 1);

Full error:

Type '{ type: "Custom"; payload: (v: number) => boolean; }' is not assignable to type '{ type: "Specific"; payload: string; } | { type: "Custom"; payload: (v: string) => boolean; }'.
  Type '{ type: "Custom"; payload: (v: number) => boolean; }' is not assignable to type '{ type: "Custom"; payload: (v: string) => boolean; }'.
    Types of property 'payload' are incompatible.
      Type '(v: number) => boolean' is not assignable to type '(v: string) => boolean'.
        Types of parameters 'v' and 'v' are incompatible.
          Type 'string' is not assignable to type 'number'.ts(2322)

I've added more details of the new generics implementation in this comment.

@ohana54
Copy link
Author

ohana54 commented May 6, 2021

Hi, sounds great!! I'll track the progress and wait for an alpha/beta version to try.

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

2 participants