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

TypeScript函数组合链式方法的类型推断问题求解

问题描述

我尝试实现一个工具函数,为指定函数直接扩展支持函数组合的可链式调用compose方法,核心代码如下:

const F = <T, U>(f: (a: T) => U) => {
  type F = {
    compose: <V,>(g: (b: U) => V) => (((a: T) => V) & F);
  };
  return Object.defineProperty(f, "compose", {
    configurable: true,
    value: <V,>(g: (b: U) => V) => F((a: T) => g(f(a)))
  }) as ((a: T) => U) & F
};
const f1 = (a: number) => a + 1;
const f2 = (a: number) => a.toString();
const identity = <T,>(a: T) => a;
const F2 = F(f2);
// ((a: number) => string) & F
// 符合预期
const F12 = F(f1).compose(f2);
// ((a: number) => string) & F
// 符合预期
const F2i = (F2).compose(identity);
// ((a: number) => string) & F
// 符合预期
const f12i = (F12).compose(identity);
// ((a: number) => number) & F
// 不符合预期,原因不明
const fi1 = F(identity).compose(f1);
/* ts(2345) 报错
  Argument of type '(a: number) => number' is not assignable to parameter of type '(b: unknown) => number'.
      Types of parameters 'a' and 'b' are incompatible.
        Type 'unknown' is not assignable to type 'number'.
  const f1: (a: number) => number
*/

现有待解决问题:

  • 类型一致的F2和F12调用compose传入identity时返回类型不一致,F12的返回类型不符合预期,无法定位原因
  • 调用F(identity).compose(f1)时报ts(2345)错误,无修复思路

注:需求为直接给原生函数挂载compose方法,不允许将函数包裹在对象中

问题根因&修复方案

根因分析

  1. 类型不一致问题:你在F函数内部定义的F类型没有和当前作用域的泛型参数T、U做强绑定,TypeScript在链式调用场景下无法正确携带累积的泛型信息,导致后续调用出现类型推断错误。
  2. identity调用报错问题:直接调用F(identity)时,TypeScript无法自动推断泛型参数T的类型,默认回退为unknown,后续传入接收number入参的f1自然会报类型不兼容错误。

修复代码

将组合函数的类型抽离到全局作用域,明确绑定泛型参数,优化类型推断逻辑:

// 抽离全局的组合函数类型,明确泛型绑定关系
type ComposeFunction<T, U> = ((a: T) => U) & {
  compose: <V>(g: (b: U) => V) => ComposeFunction<T, V>
}

const F = <T, U>(f: (a: T) => U): ComposeFunction<T, U> => {
  return Object.defineProperty(f, "compose", {
    configurable: true,
    value: <V>(g: (b: U) => V) => F((a: T) => g(f(a)))
  }) as ComposeFunction<T, U>
};

// 调用泛型函数时如果无法自动推断类型,显式传入泛型参数即可
const fi1 = F<number, number>(identity).compose(f1);

修复后验证

  • F2.compose(identity)返回类型为ComposeFunction<number, string>,符合预期
  • F12.compose(identity)返回类型和前者完全一致,无类型错误
  • 显式指定identity的泛型参数后,fi1无ts(2345)报错,类型完全符合预期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 09:36:06