Skip to content

Instantly share code, notes, and snippets.

Created September 10, 2017 20:38
Show Gist options
  • Save anonymous/9ffb548a38b6c24114d4bad360bfe8f8 to your computer and use it in GitHub Desktop.
Save anonymous/9ffb548a38b6c24114d4bad360bfe8f8 to your computer and use it in GitHub Desktop.
create tagged union from return types of action-creators
// @flow
// Helper to extract inferred return type of a function
type _ExtractReturn<B, F: (...args: any[]) => B> = B;
type ExtractReturn<F> = _ExtractReturn<*, F>;
// Use constants as normal
const AGE = 'AGE';
const NAME = 'NAME';
// only need to provide types for arguments in action-creators
// return type will be inferred
function setAge(age: number) {
return { type: AGE, payload: age }
}
function setName(name: number) {
return { type: NAME, payload: name }
}
type State = { age: number, name: string }
// Create a union type containing all the return types of
// of your chosen action-creators. The result can be used as a tagged
// union that allows flow to narrow the payload type based on 'type' property
type Actions =
ExtractReturn<typeof setAge> |
ExtractReturn<typeof setName>
function reducer(state: State = { age: 0, name: '' }, action: Actions): State {
switch(action.type) {
case AGE: {
// here, flow knows action.payload is a number
return {
...state,
age: action.payload,
}
}
case NAME: {
// here, flow knows action.payload is a string
return {
...state,
name: action.payload.toLowerCase(),
}
}
default: return state;
}
}
@wpcarro
Copy link

wpcarro commented May 9, 2018

I saw your SO question, dfroger. Thanks for reporting the issue.

I'm interested if anyone has found a way to reduce boilerplate, without sacrificing type safety? I'm looking to retrofit an existing codebase to use the ExtractReturn util, but it introduces too many false negative type errors, which is greatly disappointing.

Still would love a way to clean up the type noise...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment