Skip to content

Instantly share code, notes, and snippets.

@scorbiclife
Created March 6, 2023 11:23
Show Gist options
  • Save scorbiclife/cb9b137a61d7c29d3acef05d7131e613 to your computer and use it in GitHub Desktop.
Save scorbiclife/cb9b137a61d7c29d3acef05d7131e613 to your computer and use it in GitHub Desktop.
Simple helpers for tagged unions in typescript
// library code for non-generic discriminated unions
export type ReplaceReturnType<F, R> = F extends (...args: infer Args) => any
? (...args: Args) => R
: never;
export type TaggedUnionFactory<TUF, R> = {
[K in keyof TUF]: ReplaceReturnType<TUF[K], R>;
};
// for monomorphic types this just works well
const _actionResult = {
failure: (message: string) => ({ kind: "failure", message } as const),
value: (value: number) => ({ kind: "result", value } as const),
};
export type ActionResult = ReturnType<
typeof _actionResult[keyof typeof _actionResult]
>;
export const actionResult: TaggedUnionFactory<
typeof _actionResult,
ActionResult
> = _actionResult;
// For generic types you have to type the usage sites but it's still pretty good
export const status = {
loading: () => ({ kind: "loading" } as const),
success: <V>(value: V) => ({ kind: "success", value } as const),
error: <E>(error: E) => ({ kind: "error", error } as const),
};
// This probably requires a recent typescript version.
export type Status<V, E> = ReturnType<
| typeof status.loading
| typeof status.success<V>
| typeof status.error<E>
| never
>;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment