From f6a5dc3edee44b61c3a93aef7d7225f841f2fbec Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Thu, 7 Sep 2023 16:57:21 +0200 Subject: [PATCH 1/2] [TS migration] Migrate 'compose.js' lib to TypeScript --- src/libs/compose.js | 36 ------------------------- src/libs/compose.ts | 64 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 36 deletions(-) delete mode 100644 src/libs/compose.js create mode 100644 src/libs/compose.ts diff --git a/src/libs/compose.js b/src/libs/compose.js deleted file mode 100644 index 876aea40b6ff..000000000000 --- a/src/libs/compose.js +++ /dev/null @@ -1,36 +0,0 @@ -import _ from 'underscore'; - -/** - * This is a utility function taken directly from Redux. (We don't want to add Redux as a dependency) - * It enables functional composition, useful for the chaining/composition of HOCs. - * - * For example, instead of: - * - * export default hoc1(config1, hoc2(config2, hoc3(config3)))(Component); - * - * Use this instead: - * - * export default compose( - * hoc1(config1), - * hoc2(config2), - * hoc3(config3), - * )(Component) - * - * @returns {Function} - */ -export default function compose(...funcs) { - if (funcs.length === 0) { - return (arg) => arg; - } - - if (funcs.length === 1) { - return funcs[0]; - } - - return _.reduce( - funcs, - (a, b) => - (...args) => - a(b(...args)), - ); -} diff --git a/src/libs/compose.ts b/src/libs/compose.ts new file mode 100644 index 000000000000..6c6a65a50814 --- /dev/null +++ b/src/libs/compose.ts @@ -0,0 +1,64 @@ +/* eslint-disable rulesdir/no-useless-compose */ +/* eslint-disable @typescript-eslint/no-unsafe-return */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/ban-types */ + +import withWindowDimensions, {AvatarWithDisplayName, withInjected, withInjected2} from './test'; + +/* eslint-disable import/export */ +type Func = (...a: T) => R; + +/** + * This is a utility function taken directly from Redux. (We don't want to add Redux as a dependency) + * It enables functional composition, useful for the chaining/composition of HOCs. + * + * For example, instead of: + * + * export default hoc1(config1, hoc2(config2, hoc3(config3)))(Component); + * + * Use this instead: + * + * export default compose( + * hoc1(config1), + * hoc2(config2), + * hoc3(config3), + * )(Component) + */ +export default function compose(): (a: R) => R; + +export default function compose(f: F): F; + +/* two functions */ +export default function compose(f1: (a: A) => R, f2: Func): Func; + +/* three functions */ +export default function compose(f1: (b: B) => R, f2: (a: A) => B, f3: Func): Func; + +/* four functions */ +export default function compose(f1: (c: C) => R, f2: (b: B) => C, f3: (a: A) => B, f4: Func): Func; + +/* rest */ +export default function compose(f1: (a: unknown) => R, ...funcs: Function[]): (...args: unknown[]) => R; + +export default function compose(...funcs: Function[]): (...args: unknown[]) => R; + +export default function compose(...funcs: Function[]): Function { + if (funcs.length === 0) { + // infer the argument type so it is usable in inference down the line + return (arg: T) => arg; + } + + if (funcs.length === 1) { + return funcs[0]; + } + + return funcs.reduce( + (a, b) => + (...args: any) => + a(b(...args)), + ); +} + +const composed = compose(withInjected, withInjected2); + +const y = composed(AvatarWithDisplayName); From eb0774cc5ce8f1bd57accb1fc29dc598ce6ddd30 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Thu, 7 Sep 2023 16:57:56 +0200 Subject: [PATCH 2/2] Fix redux types --- src/libs/compose.ts | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/libs/compose.ts b/src/libs/compose.ts index 6c6a65a50814..dadc586d0f0d 100644 --- a/src/libs/compose.ts +++ b/src/libs/compose.ts @@ -1,12 +1,5 @@ -/* eslint-disable rulesdir/no-useless-compose */ -/* eslint-disable @typescript-eslint/no-unsafe-return */ -/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/ban-types */ - -import withWindowDimensions, {AvatarWithDisplayName, withInjected, withInjected2} from './test'; - /* eslint-disable import/export */ -type Func = (...a: T) => R; /** * This is a utility function taken directly from Redux. (We don't want to add Redux as a dependency) @@ -29,19 +22,36 @@ export default function compose(): (a: R) => R; export default function compose(f: F): F; /* two functions */ -export default function compose(f1: (a: A) => R, f2: Func): Func; +export default function compose(f1: (...args: A) => R1, f2: (a: R1) => R2): (...args: A) => R2; /* three functions */ -export default function compose(f1: (b: B) => R, f2: (a: A) => B, f3: Func): Func; +export default function compose(f1: (...args: A) => R1, f2: (a: R1) => R2, f3: (a: R2) => R3): (...args: A) => R3; /* four functions */ -export default function compose(f1: (c: C) => R, f2: (b: B) => C, f3: (a: A) => B, f4: Func): Func; +export default function compose(f1: (...args: A) => R1, f2: (a: R1) => R2, f3: (a: R2) => R3, f4: (a: R3) => R4): (...args: A) => R4; + +/* five functions */ +export default function compose( + f1: (...args: A) => R1, + f2: (a: R1) => R2, + f3: (a: R2) => R3, + f4: (a: R3) => R4, + f5: (a: R4) => R5, +): (...args: A) => R5; + +/* six functions */ +export default function compose( + f1: (...args: A) => R1, + f2: (a: R1) => R2, + f3: (a: R2) => R3, + f4: (a: R3) => R4, + f5: (a: R4) => R5, + f6: (a: R5) => R6, +): (...args: A) => R6; /* rest */ export default function compose(f1: (a: unknown) => R, ...funcs: Function[]): (...args: unknown[]) => R; -export default function compose(...funcs: Function[]): (...args: unknown[]) => R; - export default function compose(...funcs: Function[]): Function { if (funcs.length === 0) { // infer the argument type so it is usable in inference down the line @@ -54,11 +64,8 @@ export default function compose(...funcs: Function[]): Function { return funcs.reduce( (a, b) => - (...args: any) => + (...args: unknown[]) => + // eslint-disable-next-line @typescript-eslint/no-unsafe-return a(b(...args)), ); } - -const composed = compose(withInjected, withInjected2); - -const y = composed(AvatarWithDisplayName);