export type FilterTypeBy = { [k in keyof T]: T[k] extends Condition ? k : never; }; export type FilterMemberNames = FilterTypeBy[keyof T]; export type SubType = Pick>; export type Methods = SubType; export type Func = (...args: any[]) => A; export type AsyncAction = Func>; export type AsyncMethods = SubType; export function compose(...funcs: Func[]): Func { return (...args: any[]) => funcs.reduce( (cur, func) => ([func.apply(null, cur)]), args) [0]; } export function mixin(instance: T, mixer: (A) => A, ...keys: FilterMemberNames>[]): T { const filter = (x: keyof T) => keys.indexOf(x) >= 0; return Object.keys(instance).reduce( (cur, key: keyof T) => { const val = instance[key]; return { ...cur, [key]: filter(key) ? compose(val, mixer) : val }; }, {}); }