Skip to content

Instantly share code, notes, and snippets.

@Buslowicz
Created November 15, 2019 09:44
Show Gist options
  • Save Buslowicz/0e9128e35afd9b0ac946b8c5bae8faa7 to your computer and use it in GitHub Desktop.
Save Buslowicz/0e9128e35afd9b0ac946b8c5bae8faa7 to your computer and use it in GitHub Desktop.
Rematch Retyped
type TypedDispatcher<R> = R extends (state: any, payload?: infer P, meta?: infer M) => any
? (payload?: P, meta?: M) => Action<P, M>
: R extends (state: any, payload: infer P, meta?: infer M) => any
? (payload: P, meta?: M) => Action<P, M>
: R extends (state: any, payload: infer P, meta: infer M) => any
? (payload: P, meta: M) => Action<P, M>
: null;
type StripUnknown<T> = T extends (payload?: unknown, meta?: unknown) => Action<unknown, unknown>
? () => Action<never, never>
: T extends (payload?: infer P, meta?: unknown) => Action<infer P, unknown>
? (payload?: P) => Action<P | undefined, never>
: T extends (payload: infer P, meta?: unknown) => Action<infer P, unknown>
? (payload: P) => Action<P, never>
: T;
type Effects<S, R> = {
[ effectName: string ]: (
this: { [K in keyof R]: StripUnknown<TypedDispatcher<R[K]>> }, payload: any, rootState: S) => void;
};
type Reducers<S> = { [ reducerName: string ]: (state: S, payload?: any, meta?: any) => S };
function typedModel<S, R extends Reducers<S>, E extends Effects<S, R>>(
name: string, state: S, reducers: R, effects: E | ((dispatch: RematchDispatch) => E)) {
return { state, reducers, effects };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment