首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >功能组合式系统

功能组合式系统
EN

Stack Overflow用户
提问于 2018-03-28 07:14:35
回答 3查看 100关注 0票数 7

如何为compose添加类型

问题基本上归结为编写这种类型:

代码语言:javascript
复制
const compose = (...funcs) => x => funcs.reduce((acc, func) => func(acc), x);

并使用它:

代码语言:javascript
复制
compose(x => x + 1, x => x * 2)(3);

在本例中,推断撰写的类型为:

代码语言:javascript
复制
const compose: (...funcs: any[]) => (x: any) => any

这只是一堆any..。

是否有一种向compose添加类型的好方法?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-03-28 07:58:54

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

我还添加了一个重载,当类型没有不同,我们只有一个类型,正在处理的整个撰写。这允许在参数类型和返回类型相同的情况下传递任意数量的函数。

代码语言:javascript
复制
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); 
票数 3
EN

Stack Overflow用户

发布于 2018-03-28 07:29:39

您可以介绍一些类型信息,我通常推荐一种迭代方法,例如,早期版本不太灵活,但最终类型是正确的:

代码语言:javascript
复制
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类型中的类型。

票数 2
EN

Stack Overflow用户

发布于 2018-03-28 07:23:02

可能不会。

在TypeScript之外思考一下,考虑到带有辛德雷-米尔纳推理的ML-类型语言,两个函数的组合类型将是

代码语言:javascript
复制
compose2: (a -> b) -> (b -> c) -> a -> c
compose2 f g x = g(f x)

如果您有三个函数,则类型为

代码语言:javascript
复制
compose3: (a->b) -> (b->c) -> (c->d) -> a -> d

继续前进

代码语言:javascript
复制
compose4: (a->b) -> (b->c) -> (c->d) -> (d->e) -> a -> e

您希望编写一个组合函数,该函数接受任意数量的函数(通过rest参数),然后通过rest进行组合。这很酷,但是你真的不能锁定所有中间函数的所有中间类型,因为一般来说,它们都是非常非常不同的。

处理具有任意数量的函数的灵活性的唯一方法是使(至少)所有中间函数都具有类型。

代码语言:javascript
复制
any -> any

即使TypeScript的类型变量与ML系列中的那些语言一样复杂,但由于需要任意数量的函数,所以不可能避免使用any(除非您可能希望将所有函数限制在a->a上,或者在特定的TypeScript示例number=>number中)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49528282

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档