Skip to content

Commit

Permalink
use ts-toolbelt for 'compose' types
Browse files Browse the repository at this point in the history
  • Loading branch information
jednano committed Sep 6, 2019
1 parent 28cd255 commit 3766d01
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 82 deletions.
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
"rollup-plugin-terser": "^5.1.1",
"rollup-plugin-typescript2": "^0.24.0",
"rxjs": "^6.5.2",
"ts-toolbelt": "^3.8.63",
"typescript": "^3.5.3",
"typings-tester": "^0.3.2"
},
Expand Down
2 changes: 1 addition & 1 deletion src/applyMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export default function applyMiddleware(
dispatch: (action, ...args) => dispatch(action, ...args)
}
const chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose<typeof dispatch>(...chain)(store.dispatch)
dispatch = compose(...chain)(store.dispatch as typeof dispatch)

return {
...store,
Expand Down
91 changes: 10 additions & 81 deletions src/compose.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
type Func0<R> = () => R
type Func1<T1, R> = (a1: T1) => R
type Func2<T1, T2, R> = (a1: T1, a2: T2) => R
type Func3<T1, T2, T3, R> = (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
Expand All @@ -13,85 +10,15 @@ type Func3<T1, T2, T3, R> = (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(): <R>(a: R) => R

export default function compose<F extends Function>(f: F): F

/* two functions */
export default function compose<A, R>(f1: (b: A) => R, f2: Func0<A>): Func0<R>
export default function compose<A, T1, R>(
f1: (b: A) => R,
f2: Func1<T1, A>
): Func1<T1, R>
export default function compose<A, T1, T2, R>(
f1: (b: A) => R,
f2: Func2<T1, T2, A>
): Func2<T1, T2, R>
export default function compose<A, T1, T2, T3, R>(
f1: (b: A) => R,
f2: Func3<T1, T2, T3, A>
): Func3<T1, T2, T3, R>

/* three functions */
export default function compose<A, B, R>(
f1: (b: B) => R,
f2: (a: A) => B,
f3: Func0<A>
): Func0<R>
export default function compose<A, B, T1, R>(
f1: (b: B) => R,
f2: (a: A) => B,
f3: Func1<T1, A>
): Func1<T1, R>
export default function compose<A, B, T1, T2, R>(
f1: (b: B) => R,
f2: (a: A) => B,
f3: Func2<T1, T2, A>
): Func2<T1, T2, R>
export default function compose<A, B, T1, T2, T3, R>(
f1: (b: B) => R,
f2: (a: A) => B,
f3: Func3<T1, T2, T3, A>
): Func3<T1, T2, T3, R>

/* four functions */
export default function compose<A, B, C, R>(
f1: (b: C) => R,
f2: (a: B) => C,
f3: (a: A) => B,
f4: Func0<A>
): Func0<R>
export default function compose<A, B, C, T1, R>(
f1: (b: C) => R,
f2: (a: B) => C,
f3: (a: A) => B,
f4: Func1<T1, A>
): Func1<T1, R>
export default function compose<A, B, C, T1, T2, R>(
f1: (b: C) => R,
f2: (a: B) => C,
f3: (a: A) => B,
f4: Func2<T1, T2, A>
): Func2<T1, T2, R>
export default function compose<A, B, C, T1, T2, T3, R>(
f1: (b: C) => R,
f2: (a: B) => C,
f3: (a: A) => B,
f4: Func3<T1, T2, T3, A>
): Func3<T1, T2, T3, R>

/* rest */
export default function compose<R>(
f1: (b: any) => R,
...funcs: Function[]
): (...args: any[]) => R

export default function compose<R>(...funcs: Function[]): (...args: any[]) => R

export default function compose(...funcs: Function[]) {
const compose = <Fns extends F.Function<any[], any>[]>(
...funcs: Fns
): ((
...args: Parameters<Fns[T.Tail<Fns>['length']]>
) => F.Return<T.Head<Fns>>) => {
if (funcs.length === 0) {
// infer the argument type so it is usable in inference down the line
return <T>(arg: T) => arg
// TODO: should probably throw an error here instead
return (<T>(arg: T) => arg) as any
}

if (funcs.length === 1) {
Expand All @@ -100,3 +27,5 @@ export default function compose(...funcs: Function[]) {

return funcs.reduce((a, b) => (...args: any) => a(b(...args)))
}

export default compose

0 comments on commit 3766d01

Please sign in to comment.