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

TypeScript中如何推断泛型参数的泛型类型参数?

TypeScript操作装饰器的类型推断问题解决

问题背景

首先定义了表示操作的泛型类型:

type Operation<A, B> = {
    execute: (data: A) => B;
};

操作示例:

const op = {
    execute: (data: string) => {
        return data;
    },
};

为给操作添加事务处理功能,同时保留原操作的所有字段,实现了装饰器函数:

export const wrapInTransaction = <A, B, O extends Operation<A, B>>(
   { execute, ...rest}: O 
): O => {
    const wrappedExecute = (data: A) =>
    {
        // 添加事务逻辑
        return execute(data)
    }        
    return {
        ...rest,
        execute: wrappedExecute,
    } as O;
}

调用时出现类型错误:

const wrapped = wrapInTransaction(op);

// Argument of type '{ execute: (data: string) => string; }' is not assignable to parameter of type 'Operation<unknown, unknown>'.
//   Types of property 'execute' are incompatible.
//     Type '(data: string) => string' is not assignable to type '(data: unknown) => unknown'.
//       Types of parameters 'data' and 'data' are incompatible.
//         Type 'unknown' is not assignable to type 'string'

问题原因

TypeScript的泛型推断顺序导致了这个问题:当泛型参数顺序是<A, B, O extends Operation<A, B>>时,TypeScript会先尝试推断A和B,但此时没有足够上下文,会将A、B推断为unknown,进而导致O的约束变成Operation<unknown, unknown>,与传入的op类型不匹配。

解决方案

调整泛型参数的推断逻辑,让TypeScript先推断O的具体类型,再从O中提取A和B的类型,有两种常用方式:

方式1:使用条件类型自动提取A和B

export const wrapInTransaction = <O extends Operation<any, any>>(
  { execute, ...rest }: O
): O => {
  // 从O的execute方法中提取参数和返回值类型
  type A = Parameters<O['execute']>[0];
  type B = ReturnType<O['execute']>;

  const wrappedExecute = (data: A): B => {
    // 这里添加事务处理逻辑
    console.log("开始事务");
    const result = execute(data);
    console.log("结束事务");
    return result;
  };

  return {
    ...rest,
    execute: wrappedExecute,
  } as O;
};

方式2:调整泛型参数顺序并使用infer

export const wrapInTransaction = <O extends Operation<infer A, infer B>>(
  { execute, ...rest }: O
): O => {
  const wrappedExecute = (data: A): B => {
    // 添加事务逻辑
    return execute(data);
  };

  return {
    ...rest,
    execute: wrappedExecute,
  } as O;
};

两种方式都能让TypeScript正确推断出op的类型,进而正确匹配A为string、B为string,避免类型不兼容的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 05:07:15