suchipi/safety-match

Generic types

Closed this issue · 3 comments

TmLev commented

Is it possible to define generic type as one of the variants?

My attempt:

const LoadState = makeTaggedUnion({
  Unstarted: none,
  Loading: (percentLoaded: number) => percentLoaded,
  Loaded: <T>(response: T) => response,
  Error: (error: Error) => error,
});

type LoadState<T> = MemberType<typeof LoadState> // Doesn't really work since `LoadState` is not generic.

Due to limitations in TypeScript, you can't really do generics with these values, since they're not functions or classes. But, you can do something pretty close by using a function to create tagged unions, like so:

function makeMaybe<T>() {
  return makeTaggedUnion({
    Some: (data: T) => ({ data }),
    None: none,
  });
}

const Maybe_String = makeMaybe<string>();
const Maybe_Number = makeMaybe<number>();

const data1 = Maybe_String.Some("hi");
const data2 = Maybe_Number.Some(456);

data1.match({
  Some: ({ data }) => data, // data is string here
  None: () => null,
});

data2.match({
  Some: ({ data }) => data, // data is number here
  None: () => null,
});

It's not as nice, but it works.

TmLev commented

Thanks!

Unfortunately, this approach cannot be used in context where, for example, type of Maybe.Some is controlled by caller, since it would require creating required type on each invocation, but it works for simple cases.

Here's a solution that allows Maybe.Some to still be controlled by the caller: #15 (comment)