Skip to content

Instantly share code, notes, and snippets.

@tvler
Last active April 22, 2020 00:39
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tvler/ccbb3136b0d8c6c48ca53d98382dcb05 to your computer and use it in GitHub Desktop.
Save tvler/ccbb3136b0d8c6c48ca53d98382dcb05 to your computer and use it in GitHub Desktop.
Implicitly type an action payload by an action type
type ActionTypes = 'actionA' | 'actionB' | 'actionC' | 'actionNoPayload';
type ActionPayloads = {
actionA: { payload: number };
actionB: { payload: string };
actionC: { foo: boolean; bar: boolean };
};
type Actions = {
[key in ActionTypes]: {
type: key;
} & (key extends keyof ActionPayloads ? ActionPayloads[key] : {})
};
type Action = Actions[keyof Actions];
// Pass
const testA: Action = { type: 'actionA', payload: 1 };
const testB: Action = { type: 'actionB', payload: 'string' };
const testC: Action = { type: 'actionC', foo: true, bar: false };
const testD: Action = { type: 'actionNoPayload' };
// Fail
const testUnexpectedActionTypeError: Action = { type: 'not typed' };
const testUnexpectedPayloadError: Action = { type: 'actionNoPayload', payload: 'error' };
const testExpectedPayloadError: Action = { type: 'actionA' };
const testUnexpectedPayloadValueError: Action = { type: 'actionA', payload: 'error' };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment