You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何我的其中一个compose函数无法正确推导类型?

函数组合类型推导问题:compose 与 composeR 的差异及修复

问题背景

定义了两个函数组合工具compose和composeR,二者逻辑完全一致,仅参数顺序相反:将一个函数的输出作为另一个函数的输入完成组合。在组合简单的数值递增、转字符串函数时,二者的类型推导均正常;但组合Option Functor和Either Functor的map方法时,compose出现类型推导错误,composeR却能正常工作。

相关代码示例:

// compose与composeR定义
type Compose = <A, B, C>(f: (x: B) => C, g: (x: A) => B) => (x: A) => C
const compose: Compose = (f, g) => x => f(g(x))

type ComposeR = <A, B, C>(g: (x: A) => B, f: (x: B) => C) => (x: A) => C
const composeR: ComposeR = (g, f) => x => f(g(x))

// Option与Either的Functor实现
const optionFunctor: Functor1<'Option'> = { /* ... */ }
const eitherFunctor: Functor2<'Either'> = { /* ... */ }

// 组合map函数时的错误场景
const map1 = optionFunctor.map
const map2 = eitherFunctor.map
const composed1 = compose(map1, map2) // 类型推导错误
const composed2 = composeR(map1, map2) // 类型推导正常

问题原因

核心在于TypeScript的类型推导顺序与函数参数顺序强相关:

  • compose的参数顺序是(f: (B) => C, g: (A) => B),TypeScript会优先推导第一个传入的f(即optionFunctor.map)的类型。但Functor的map是多态高阶函数(需要上下文确定输入输出类型),此时没有足够信息确定B的类型,导致后续g的类型无法与f匹配,最终推导失败。
  • composeR的参数顺序是(g: (A) => B, f: (B) => C),先传入的g(即eitherFunctor.map)会被优先推导,确定A和B的类型后,第二个参数f的类型可以基于已确定的B完成匹配,因此推导顺利完成。

补充说明:Option的map类型大致为<A, B>(fn: (a: A) => B) => (o: Option<A>) => Option<B>,Either的map类型大致为<E, A, B>(fn: (a: A) => B) => (e: Either<E, A>) => Either<E, B>,这类多态函数的类型推导严重依赖上下文参数的顺序。

修复方案

1. 调整compose的参数顺序(推荐)

直接将compose的参数顺序改为与composeR一致,让类型推导逻辑自然对齐:

type Compose = <A, B, C>(g: (x: A) => B, f: (x: B) => C) => (x: A) => C
const compose: Compose = (g, f) => x => f(g(x))

2. 显式指定类型参数(临时 workaround)

如果不想修改参数顺序,可以在调用compose时显式指定类型参数,帮TypeScript明确类型关系:

// 需根据实际场景替换E、A、B为具体类型
const composed1 = compose<Either<E, A>, Option<A>, Option<B>>(map1, map2)

3. 优化compose的类型参数顺序

调整类型参数的声明顺序,让TypeScript优先推导两个函数的重叠类型B,再推导A和C,部分场景下可自动完成推导:

type Compose = <B, C, A>(f: (x: B) => C, g: (x: A) => B) => (x: A) => C
const compose: Compose = (f, g) => x => f(g(x))

内容的提问来源于stack exchange,提问作者Shnd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 14:18:13