输入功能组成系统

Ben*_*Ben 7 javascript typescript

我该如何添加类型compose
问题基本上归结为为此编写类型:

const compose = (...funcs) => x => funcs.reduce((acc, func) => func(acc), x);
Run Code Online (Sandbox Code Playgroud)

并使用它:

compose(x => x + 1, x => x * 2)(3);
Run Code Online (Sandbox Code Playgroud)

在此示例中,compose的类型被推断为:

const compose: (...funcs: any[]) => (x: any) => any
Run Code Online (Sandbox Code Playgroud)

这只是一堆any......

有没有一种很好的方法来添加类型compose

Tit*_*mir 3

虽然不可能输入这样的函数来接受任意数量的函数,但我们可以编写一个compose重载最多给定数量函数的版本。对于大多数实际用途来说,它应该足以允许组合最多 5 个函数,并且我们可以根据需要随时添加更多重载。

当类型没有不同并且我们只有一种类型在整个撰写过程中处理时,我还添加了一个重载。如果参数类型和返回类型相同,则允许传入任意数量的函数。

function compose<A, B, C, D, E, F>(fn: (p: A) => B, fn2: (p: B) => C, fn3: (p: C) => D, fn4: (p: D) => E, fn5: (p: E) => F): (p: A) => F
function compose<A, B, C, D, E>(fn: (p: A) => B, fn2: (p: B) => C, fn3: (p: C) => D, fn4: (p: D) => E): (p: A) => E
function compose<A, B, C, D>(fn: (p: A) => B, fn2: (p: B) => C, fn3: (p: C) => D): (p: A) => D
function compose<A, B, C>(fn: (p: A) => B, fn2: (p: B) => C): (p: A) => C
function compose<T>(...funcs: Array<(p: T) => T>) : (p: T) => T // Special case of parameter and return having the same type
function compose(...funcs: Array<(p: any) => any>) {
    return (x: any) => funcs.reduce((acc, func) => func(acc), x)
};

// Usage
// First argument type must be specified, rest are inferred correctly
let fn = compose((x : number) => x + 1, x => x * 2); // fn will be (p: number) => number
let d = fn(3); // d will be number 

let fn2 = compose((x : number) => x + 1, x => x * 2, x=> x.toString(), x => x.toLowerCase()); // fn will be (p: number) => string and we get intelisense and type safety in each function 

// Any number of functions but a single type
let fnMany = compose((x : number) => x + 1, x => x * 2, x => x * 2, x => x * 2, x => x * 2, x => x * 2, x => x * 2); 
Run Code Online (Sandbox Code Playgroud)