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

如何让TypeScript装饰器从被装饰函数正确推导返回类型?

解决方案

要让装饰器自动从被装饰方法的返回类型推导泛型R,同时强制options.returnValue匹配该类型,你需要调整泛型推导逻辑,让方法的返回类型优先主导推断,而非从配置参数反向推导。

核心思路

通过提取被装饰方法的返回类型作为约束,强制returnValue必须匹配该类型,而不是让returnValue的类型决定泛型R。

实现代码

// 提取函数返回类型的工具类型
type ExtractReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

function checkBeforeExecution(options: { check: () => boolean; returnValue: unknown }) {
  return function <T extends (...args: any[]) => any>(
    target: any,
    propertyKey: string,
    descriptor: TypedPropertyDescriptor<T>
  ) {
    // 从方法类型中提取返回类型
    type MethodReturn = ExtractReturnType<T>;
    // 校验并约束returnValue必须匹配方法返回类型
    const validatedReturnValue = options.returnValue as MethodReturn;

    const originalMethod = descriptor.value!;
    descriptor.value = function (...args: Parameters<T>) {
      if (!options.check()) {
        return validatedReturnValue;
      }
      return originalMethod.apply(this, args);
    } as T;

    return descriptor;
  };
}

测试示例

class Demo {
  // 正常工作:returnValue为boolean,匹配方法返回类型
  @checkBeforeExecution({ check: () => Math.random() > 0.5, returnValue: false })
  returnsBoolean(): boolean {
    return true;
  }

  // 类型报错:returnValue是string,与方法返回number不匹配
  // @checkBeforeExecution({ check: () => false, returnValue: "failed" })
  returnsNumber(): number {
    return 100;
  }
}

原理说明

  1. 装饰器工厂函数先接收options,但不立即推导泛型;
  2. 内部函数接收被装饰方法的类型T,通过ExtractReturnType工具类型提取其返回类型;
  3. 强制将options.returnValue断言为方法返回类型,若类型不匹配,TypeScript会直接抛出错误;
  4. 泛型推导优先级完全由被装饰方法的返回类型主导,无需显式指定泛型参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 11:42:51