type CallBackType = (...args: readonly unknown[]) => void; type KeyType = string | string[]; function isFunction(func: CallBackType) { return typeof func === 'function'; } function Diff(this: any, key: string, _this: any, nextProps: any) { this.result = { key, loading: [], success: [], error: [] }; const prop = _this.props[key]; const nProp = nextProps[key]; if (prop !== nProp) { const {result, payload} = nProp || {}; if (nProp.loading) { this.result.loading.push(payload); } else if (nProp.status === 200 && nProp.success) { this.result.success.push(result, payload, nProp.message); } else { this.result.error.push(nProp.message || nProp.error); } } } Diff.prototype.loading = function dLoading(callback: CallBackType) { if (isFunction(callback) && this.result.loading.length > 0) { callback(...this.result.loading); } return this; }; Diff.prototype.success = function dSuccess(callback: CallBackType) { if (isFunction(callback) && this.result.success.length > 0) { callback(...this.result.success); } return this; }; Diff.prototype.error = function dError(callback: CallBackType) { if (isFunction(callback) && this.result.error.length > 0) { callback(...this.result.error); } return this; }; Diff.prototype.result = { loading: [], success: [], error: [] }; function Manager(this: any, key: KeyType, _this: any, nextProps: any) { this.diffs = []; if (key instanceof Array) { key.forEach((k) => { this.diffs.push(new (Diff as any)(k, _this, nextProps)); }); } else if (typeof key === 'string') { this.diffs.push(new (Diff as any)(key, _this, nextProps)); } else { throw Error(`props key should be Array or string , but [${typeof key}]`); } } Manager.prototype.diffs = []; Manager.prototype.loading = function loading(callback: CallBackType) { this.diffs.forEach((d: any) => { d.loading(callback); }); return this; }; Manager.prototype.success = function success(callback: CallBackType) { this.diffs.forEach((d: any) => d.success(callback)); return this; }; Manager.prototype.error = function error(callback: CallBackType) { this.diffs.forEach((d: any) => d.error(callback)); return this; }; export default function receive(this: any, key: KeyType, nextProps: any) { return new (Manager as any)(key, this, nextProps); }