Skip to content

Commit 085eaec

Browse files
aikoventimdorr
authored andcommitted
Improve typings for compose function (reduxjs#1868)
1 parent 13add05 commit 085eaec

File tree

2 files changed

+66
-21
lines changed

2 files changed

+66
-21
lines changed

index.d.ts

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,11 @@ export function bindActionCreators<
357357

358358
/* compose */
359359

360+
type Func0<R> = () => R;
361+
type Func1<T1, R> = (a1: T1) => R;
362+
type Func2<T1, T2, R> = (a1: T1, a2: T2) => R;
363+
type Func3<T1, T2, T3, R> = (a1: T1, a2: T2, a3: T3, ...args: any[]) => R;
364+
360365
/**
361366
* Composes single-argument functions from right to left. The rightmost
362367
* function can take multiple arguments as it provides the signature for the
@@ -367,27 +372,54 @@ export function bindActionCreators<
367372
* to left. For example, `compose(f, g, h)` is identical to doing
368373
* `(...args) => f(g(h(...args)))`.
369374
*/
370-
export function compose(): <R>(a: R, ...args: any[]) => R;
375+
export function compose(): <R>(a: R) => R;
371376

372-
export function compose<A, R>(
373-
f1: (b: A) => R,
374-
f2: (...args: any[]) => A
375-
): (...args: any[]) => R;
377+
export function compose<F extends Function>(f: F): F;
376378

379+
/* two functions */
380+
export function compose<A, R>(
381+
f1: (b: A) => R, f2: Func0<A>
382+
): Func0<R>;
383+
export function compose<A, T1, R>(
384+
f1: (b: A) => R, f2: Func1<T1, A>
385+
): Func1<T1, R>;
386+
export function compose<A, T1, T2, R>(
387+
f1: (b: A) => R, f2: Func2<T1, T2, A>
388+
): Func2<T1, T2, R>;
389+
export function compose<A, T1, T2, T3, R>(
390+
f1: (b: A) => R, f2: Func3<T1, T2, T3, A>
391+
): Func3<T1, T2, T3, R>;
392+
393+
/* three functions */
377394
export function compose<A, B, R>(
378-
f1: (b: B) => R,
379-
f2: (a: A) => B,
380-
f3: (...args: any[]) => A
381-
): (...args: any[]) => R;
382-
395+
f1: (b: B) => R, f2: (a: A) => B, f3: Func0<A>
396+
): Func0<R>;
397+
export function compose<A, B, T1, R>(
398+
f1: (b: B) => R, f2: (a: A) => B, f3: Func1<T1, A>
399+
): Func1<T1, R>;
400+
export function compose<A, B, T1, T2, R>(
401+
f1: (b: B) => R, f2: (a: A) => B, f3: Func2<T1, T2, A>
402+
): Func2<T1, T2, R>;
403+
export function compose<A, B, T1, T2, T3, R>(
404+
f1: (b: B) => R, f2: (a: A) => B, f3: Func3<T1, T2, T3, A>
405+
): Func3<T1, T2, T3, R>;
406+
407+
/* four functions */
383408
export function compose<A, B, C, R>(
384-
f1: (b: C) => R,
385-
f2: (a: B) => C,
386-
f3: (a: A) => B,
387-
f4: (...args: any[]) => A
388-
): (...args: any[]) => R;
389-
390-
export function compose<R>(
391-
f1: (a: any) => R,
409+
f1: (b: C) => R, f2: (a: B) => C, f3: (a: A) => B, f4: Func0<A>
410+
): Func0<R>;
411+
export function compose<A, B, C, T1, R>(
412+
f1: (b: C) => R, f2: (a: B) => C, f3: (a: A) => B, f4: Func1<T1, A>
413+
): Func1<T1, R>;
414+
export function compose<A, B, C, T1, T2, R>(
415+
f1: (b: C) => R, f2: (a: B) => C, f3: (a: A) => B, f4: Func2<T1, T2, A>
416+
): Func2<T1, T2, R>;
417+
export function compose<A, B, C, T1, T2, T3, R>(
418+
f1: (b: C) => R, f2: (a: B) => C, f3: (a: A) => B, f4: Func3<T1, T2, T3, A>
419+
): Func3<T1, T2, T3, R>;
420+
421+
/* rest */
422+
export function compose<A, B, C, R>(
423+
f1: (b: C) => R, f2: (a: B) => C, f3: (a: A) => B,
392424
...funcs: Function[]
393425
): (...args: any[]) => R;

test/typescript/compose.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,20 @@ const t4: (a: string) => number = compose(
1616

1717

1818
const t5: number = compose(stringToNumber, numberToString, numberToNumber)(5);
19-
const t6: string = compose(numberToString, stringToNumber, numberToString, numberToNumber)(5);
19+
const t6: string = compose(numberToString, stringToNumber, numberToString,
20+
numberToNumber)(5);
2021

21-
const t7: string = compose<string>(
22-
numberToString, numberToNumber, stringToNumber, numberToString, stringToNumber)("fo");
22+
const t7: string = compose(
23+
numberToString, numberToNumber, stringToNumber, numberToString,
24+
stringToNumber)("fo");
25+
26+
27+
const multiArgFn = (a: string, b: number, c: boolean): string => 'foo'
28+
29+
const t8: string = compose(multiArgFn)('bar', 42, true);
30+
const t9: number = compose(stringToNumber, multiArgFn)('bar', 42, true);
31+
const t10: string = compose(numberToString, stringToNumber,
32+
multiArgFn)('bar', 42, true);
33+
34+
const t11: number = compose(stringToNumber, numberToString, stringToNumber,
35+
multiArgFn)('bar', 42, true);

0 commit comments

Comments
 (0)