UNPKG

@mikhail.shtanko/redux-oop

Version:

Powerful extensitions for building class-based Redux architecture powered by TypeScript.

44 lines (40 loc) 1.77 kB
import 'reflect-metadata'; import State from './state'; import { Reducer as ReduxReducer } from 'redux'; import Action from './action'; import { METADATA_KEY_ACTION } from './constants'; export default class Reducer<T extends State> { initialState: T; mapping: Map<string, Array<(state: T, action: any) => T>> = new Map(); name: string | null; private executeReducer(state: T, action: Action, actionType?: string): T { const funcs = this.mapping.get(actionType || action.type); let resState = state; if (funcs != null) { for (const func of funcs) { resState = func.bind(this)(resState, action); } } return resState; } protected call(state: T = this.initialState, action: Action): T { const resState = this.executeReducer(state, action); // for 'any' action type return this.executeReducer(resState, action, Object.name); } create(): ReduxReducer<T, any> { // idk why all methods are in prototype class const proto = Object.getPrototypeOf(this); const methodNames: string[] = Object.getOwnPropertyNames(proto).filter(x => x != 'constructor' && !x.startsWith('_')); for (const key of methodNames) { const metaActionType: string = Reflect.getMetadata(METADATA_KEY_ACTION, this, key); if (metaActionType == null) continue; const func: (state: T, action: any) => T = (this as any)[key]; if (!this.mapping.has(metaActionType)) this.mapping.set(metaActionType, []); this.mapping.get(metaActionType)!.push(func); } return this.call.bind(this); } }