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

如何正确编写TypeScript透传函数装饰器?探讨规范实现方式

函数增强的TypeScript类型规范实现方案

问题描述

现有一个enhanceFn函数,用于给传入的函数添加额外功能(如日志记录),同时希望保持原函数的类型不变。当前实现使用as unknown as T覆盖返回类型,参数采用any[]类型,疑问点在于:

  • 这种实现是否属于“正确”/规范的方式?
  • 是否存在更优的实现方案?

原实现代码:

const enhanceFn = <T extends (...args: any[])=>any>(fn: T):T=>(...args: any[])=>{
    try{
        return fn(...args)
    } catch (e){
        console.log(e)
    }
} as unknown as T

const fn = (value: string)=>{ throw new Error(value) }

const enhancedFn = enhanceFn(fn)

enhancedFn('throw this error')

现有实现的问题

  • 参数类型不严谨:使用any[]作为参数类型,完全丢失了原函数的参数类型信息,TypeScript无法对增强后函数的参数做类型校验,违背了类型安全的初衷。
  • 类型断言的风险:as unknown as T是强制类型断言,会掩盖潜在的类型不匹配问题。比如原函数有明确的非undefined返回值类型时,增强后的函数在捕获错误后会返回undefined(catch块无返回语句),此时实际返回值和T的类型定义矛盾,断言强行忽略了这个问题。

更优实现方案

方案1:精准捕获类型,保持行为一致

通过Parameters<T>和ReturnType<T>泛型工具类型,精准获取原函数的参数和返回值类型,同时在捕获错误后重新抛出,保证增强函数的行为与原函数一致(要么返回原类型值,要么抛出错误):

const enhanceFn = <T extends (...args: any[]) => any>(fn: T): T => {
  return (...args: Parameters<T>): ReturnType<T> => {
    try {
      return fn(...args);
    } catch (e) {
      console.error("捕获到错误:", e);
      throw e; // 重新抛出错误,确保返回类型与原函数完全匹配
    }
  } as T;
};

方案2:简化泛型定义,自动推断类型

拆分参数和返回值的泛型参数,让TypeScript自动推断类型,无需显式约束T,同时避免不必要的类型断言:

const enhanceFn = <Args extends any[], Return>(fn: (...args: Args) => Return) => {
  return (...args: Args): Return => {
    try {
      return fn(...args);
    } catch (e) {
      console.error("捕获到错误:", e);
      throw e;
    }
  };
};

方案3:错误后返回默认值(需匹配原类型)

如果希望捕获错误后不抛出,而是返回一个符合原函数返回类型的值,需要确保原函数的返回类型包含该默认值的类型:

// 适用于原函数返回类型允许undefined的场景
const enhanceFn = <T extends (...args: any[]) => any>(fn: T): T => {
  return (...args: Parameters<T>): ReturnType<T> => {
    try {
      return fn(...args);
    } catch (e) {
      console.error("捕获到错误:", e);
      // 返回符合原类型的默认值,这里假设原类型允许undefined
      return undefined as ReturnType<T>;
    }
  } as T;
};

总结

原实现的any[]和强制类型断言虽然能“运行”,但不符合TypeScript的类型安全规范,存在潜在风险。更优方案的核心是精准捕获原函数的类型信息,并确保增强后的函数行为与类型定义一致,既保留类型校验能力,又避免不必要的类型断言。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 22:45:39