diff --git a/package-lock.json b/package-lock.json index a481f01266..6384aa2655 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7297,6 +7297,12 @@ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, + "ts-toolbelt": { + "version": "3.8.63", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-3.8.63.tgz", + "integrity": "sha512-OlsFC8uF1mpN2O7DlvSkgnXzOvubO790eFhTvZBFI+WLge2BYzkQk73Q3yF0R8usxhkqbemLomqRhCGWasoIKw==", + "dev": true + }, "tsconfig-paths": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.8.0.tgz", diff --git a/package.json b/package.json index 69a3e8570a..db399e0d51 100644 --- a/package.json +++ b/package.json @@ -88,6 +88,7 @@ "rollup-plugin-terser": "^5.1.1", "rollup-plugin-typescript2": "^0.24.0", "rxjs": "^6.5.3", + "ts-toolbelt": "^3.8.63", "typescript": "^3.5.3" }, "npmName": "redux", diff --git a/src/applyMiddleware.ts b/src/applyMiddleware.ts index f735843252..366f630a17 100644 --- a/src/applyMiddleware.ts +++ b/src/applyMiddleware.ts @@ -72,7 +72,7 @@ export default function applyMiddleware( dispatch: (action, ...args) => dispatch(action, ...args) } const chain = middlewares.map(middleware => middleware(middlewareAPI)) - dispatch = compose(...chain)(store.dispatch) + dispatch = compose(...chain)(store.dispatch as typeof dispatch) return { ...store, diff --git a/src/compose.ts b/src/compose.ts index fcbfd70d7b..1161f69463 100644 --- a/src/compose.ts +++ b/src/compose.ts @@ -1,7 +1,4 @@ -type Func0 = () => R -type Func1 = (a1: T1) => R -type Func2 = (a1: T1, a2: T2) => R -type Func3 = (a1: T1, a2: T2, a3: T3, ...args: any[]) => R +import { F, T } from 'ts-toolbelt' /** * Composes single-argument functions from right to left. The rightmost @@ -13,85 +10,15 @@ type Func3 = (a1: T1, a2: T2, a3: T3, ...args: any[]) => R * to left. For example, `compose(f, g, h)` is identical to doing * `(...args) => f(g(h(...args)))`. */ -export default function compose(): (a: R) => R - -export default function compose(f: F): F - -/* two functions */ -export default function compose(f1: (b: A) => R, f2: Func0): Func0 -export default function compose( - f1: (b: A) => R, - f2: Func1 -): Func1 -export default function compose( - f1: (b: A) => R, - f2: Func2 -): Func2 -export default function compose( - f1: (b: A) => R, - f2: Func3 -): Func3 - -/* three functions */ -export default function compose( - f1: (b: B) => R, - f2: (a: A) => B, - f3: Func0 -): Func0 -export default function compose( - f1: (b: B) => R, - f2: (a: A) => B, - f3: Func1 -): Func1 -export default function compose( - f1: (b: B) => R, - f2: (a: A) => B, - f3: Func2 -): Func2 -export default function compose( - f1: (b: B) => R, - f2: (a: A) => B, - f3: Func3 -): Func3 - -/* four functions */ -export default function compose( - f1: (b: C) => R, - f2: (a: B) => C, - f3: (a: A) => B, - f4: Func0 -): Func0 -export default function compose( - f1: (b: C) => R, - f2: (a: B) => C, - f3: (a: A) => B, - f4: Func1 -): Func1 -export default function compose( - f1: (b: C) => R, - f2: (a: B) => C, - f3: (a: A) => B, - f4: Func2 -): Func2 -export default function compose( - f1: (b: C) => R, - f2: (a: B) => C, - f3: (a: A) => B, - f4: Func3 -): Func3 - -/* rest */ -export default function compose( - f1: (b: any) => R, - ...funcs: Function[] -): (...args: any[]) => R - -export default function compose(...funcs: Function[]): (...args: any[]) => R - -export default function compose(...funcs: Function[]) { +const compose = []>( + ...funcs: Fns +): (( + ...args: Parameters['length']]> +) => F.Return>) => { if (funcs.length === 0) { // infer the argument type so it is usable in inference down the line - return (arg: T) => arg + // TODO: should probably throw an error here instead + return ((arg: T) => arg) as any } if (funcs.length === 1) { @@ -100,3 +27,5 @@ export default function compose(...funcs: Function[]) { return funcs.reduce((a, b) => (...args: any) => a(b(...args))) } + +export default compose