Skip to content

Instantly share code, notes, and snippets.

@ratbeard
Created February 25, 2019 20:41
Show Gist options
  • Save ratbeard/61f25316287562069e46959b8bbf2a7c to your computer and use it in GitHub Desktop.
Save ratbeard/61f25316287562069e46959b8bbf2a7c to your computer and use it in GitHub Desktop.
import { typeSwitch } from './typeSwitch';
interface Circle {
type: 'circle';
radius: number;
}
interface Square {
type: 'square';
width: number;
}
type Shape = Circle | Square;
it('forces you to handle all possible types, unlike if', () => {
const circle = { type: 'circle', radius: 3.14 } as Shape;
const result = typeSwitch(circle, {
circle: () => 'round',
square: () => 'pointy',
});
expect(result).toEqual('round');
});
export function typeSwitch<
TResult,
T extends { type: string },
>(
object: T,
handlers: {[k in T['type']]: () => TResult},
): TResult {
const { type } = object;
// https://basarat.gitbooks.io/typescript/docs/types/index-signatures.html
const handler = (handlers as any)[type] as () => TResult;
if (!handler) {
throw new Error(`Invariant Error: Unexpected type "${type}" given to typeSwitch`);
}
return handler();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment