Skip to content

Commit

Permalink
Add explicit VariantPattern name
Browse files Browse the repository at this point in the history
  • Loading branch information
gvergnaud committed Sep 6, 2021
1 parent b64b054 commit 382a730
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 26 deletions.
8 changes: 7 additions & 1 deletion src/variants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ import { Pattern } from './types/Pattern';

export type Variant<k, d = never> = Compute<{ tag: k; value: d }>;

/**
* VariantPatterns can be used to match a Variant in a
* `match` expression.
*/
type VariantPattern<k, p> = { tag: k; value: p };

type AnyVariant = Variant<string, unknown>;

type Narrow<variant extends AnyVariant, k extends variant['tag']> = Extract<
Expand All @@ -16,7 +22,7 @@ type Constructor<k, v> = [v] extends [never]
? <t>(value: t) => Variant<k, t>
: {
(value: v): Variant<k, v>;
<p extends Pattern<v>>(pattern: p): Variant<k, p>;
<p extends Pattern<v>>(pattern: p): VariantPattern<k, p>;
};

type Impl<variant extends AnyVariant> = {
Expand Down
50 changes: 25 additions & 25 deletions tests/variants.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,31 @@ describe('Variants', () => {
).toEqual(false);
});

it('Variants with type parameters should work', () => {
const toString = (maybeShape: Maybe<Shape>) =>
match(maybeShape)
.with(Nothing(), () => 'Nothing')
.with(
Just(Circle({ radius: select() })),
(radius) => `Just Circle { radius: ${radius} }`
)
.with(
Just(Square(select())),
({ sideLength }) => `Just Square sideLength: ${sideLength}`
)
.with(
Just(Rectangle(select())),
({ x, y }) => `Just Rectangle { x: ${x}, y: ${y} }`
)
.with(Just(Blob(select())), (area) => `Just Blob { area: ${area} }`)
.exhaustive();

expect(toString(Just(Circle({ radius: 20 })))).toEqual(
`Just Circle { radius: 20 }`
);
expect(toString(Nothing())).toEqual(`Nothing`);
});

it('should be possible to put a union type in a variant', () => {
// with a normal union

Expand Down Expand Up @@ -101,31 +126,6 @@ describe('Variants', () => {
);
});

it('Variants with type parameters should work', () => {
const toString = (maybeShape: Maybe<Shape>) =>
match(maybeShape)
.with(Nothing(), () => 'Nothing')
.with(
Just(Circle({ radius: select() })),
(radius) => `Just Circle { radius: ${radius} }`
)
.with(
Just(Square(select())),
({ sideLength }) => `Just Square sideLength: ${sideLength}`
)
.with(
Just(Rectangle(select())),
({ x, y }) => `Just Rectangle { x: ${x}, y: ${y} }`
)
.with(Just(Blob(select())), (area) => `Just Blob { area: ${area} }`)
.exhaustive();

expect(toString(Just(Circle({ radius: 20 })))).toEqual(
`Just Circle { radius: 20 }`
);
expect(toString(Nothing())).toEqual(`Nothing`);
});

it('should be possible to create a variant with several type parameters', () => {
// Result
type Result<E, A> = Variant<'Success', A> | Variant<'Err', E>;
Expand Down

0 comments on commit 382a730

Please sign in to comment.