如何为compose添加类型
问题基本上归结为编写这种类型:
const compose = (...funcs) => x => funcs.reduce((acc, func) => func(acc), x);并使用它:
compose(x => x + 1, x => x * 2)(3);在本例中,推断撰写的类型为:
const compose: (...funcs: any[]) => (x: any) => any这只是一堆any..。
是否有一种向compose添加类型的好方法?
发布于 2018-03-28 07:58:54
虽然不可能输入这样的函数来接受任意数量的函数,但是我们可以编写一个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); 发布于 2018-03-28 07:29:39
您可以介绍一些类型信息,我通常推荐一种迭代方法,例如,早期版本不太灵活,但最终类型是正确的:
interface Composer {
(...funcs: { (arg: any): any }[]): (arg: any) => number;
}
const compose: Composer = (...funcs) => x => funcs.reduce((acc, func) => func(acc), x);
// result: number
const result = compose(x => x + 1, x => x * 2)(3);您可以将其迭代到特定的用途中。例如,可能最终类型需要泛型类型,因此可以将Composer升级到Composer<T>。或者,您可能希望降低中间类型的允许性(它们目前可以是任意类型,但也可以改进)。
最终,应该由您决定在哪里修复类型,或者引入动态类型,或者停止完全关注Composer类型中的类型。
发布于 2018-03-28 07:23:02
可能不会。
在TypeScript之外思考一下,考虑到带有辛德雷-米尔纳推理的ML-类型语言,两个函数的组合类型将是
compose2: (a -> b) -> (b -> c) -> a -> c
compose2 f g x = g(f x)如果您有三个函数,则类型为
compose3: (a->b) -> (b->c) -> (c->d) -> a -> d继续前进
compose4: (a->b) -> (b->c) -> (c->d) -> (d->e) -> a -> e您希望编写一个组合函数,该函数接受任意数量的函数(通过rest参数),然后通过rest进行组合。这很酷,但是你真的不能锁定所有中间函数的所有中间类型,因为一般来说,它们都是非常非常不同的。
处理具有任意数量的函数的灵活性的唯一方法是使(至少)所有中间函数都具有类型。
any -> any即使TypeScript的类型变量与ML系列中的那些语言一样复杂,但由于需要任意数量的函数,所以不可能避免使用any(除非您可能希望将所有函数限制在a->a上,或者在特定的TypeScript示例number=>number中)。
https://stackoverflow.com/questions/49528282
复制相似问题