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

使用TypeScript 5装饰器时遭遇返回类型无法赋值给unknown的类型错误

TypeScript 5新装饰器类型错误问题

尝试实现TypeScript 5的新装饰器时,碰到了无法理解的类型不匹配错误。

报错信息

装饰器函数返回类型 '(this: ProductsService, ...args: any[]) => unknown' 无法赋值给类型 'void | ((mockProducts: any) => Promise<TProductsDtoOutput[]>)'。
类型 '(this: ProductsService, ...args: any[]) => unknown' 无法赋值给类型 '(mockProducts: any) => Promise<TProductsDtoOutput[]>'。
类型 'unknown' 无法赋值给类型 'Promise<TProductsDtoOutput[]>'。

代码示例

export function loggedMethod<This, Args extends any[], Return, Fn extends (this: This, ...args: Args) => Return>(
  target: Fn,
  context: ClassMethodDecoratorContext<This, Fn>
) {
  const methodName = String(context.name);
  function replacementMethod(this: This, ...args: Args): Return {
    console.log(`LOG : Entering Method "${methodName}"`);
    const result = target.call(this, ...args);
    console.log(`LOG : Exiting Method "${methodName}"`);
    return result;
  }

  return replacementMethod;
}

type TProductsDtoOutput = {
    all:string
}


export class ProductsService {
  @loggedMethod
  async getAll(mockProducts:any): Promise<TProductsDtoOutput[]> {
    const result = mockProducts.map((product:any) => {
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      const { id, ...rest } = product;

      return rest as TProductsDtoOutput;
    });
    return result
  }
}

编辑补充

即使强制转换返回类型,错误依然存在:
即使强制转换返回类型,错误依然存在


问题原因

TypeScript 5对装饰器的类型推导在处理异步函数时出现偏差,原装饰器的泛型参数Fn未被正确推断,导致返回的替换函数类型被识别为unknown,无法匹配原方法的Promise<TProductsDtoOutput[]>返回类型。

解决办法

简化装饰器的泛型定义,让TypeScript能正确推导返回类型,修改后的装饰器代码如下:

export function loggedMethod<This, Args extends any[], Return>(
  target: (this: This, ...args: Args) => Return,
  context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>
) {
  const methodName = String(context.name);
  const replacementMethod = function(this: This, ...args: Args): Return {
    console.log(`LOG : Entering Method "${methodName}"`);
    const result = target.call(this, ...args);
    console.log(`LOG : Exiting Method "${methodName}"`);
    return result;
  };

  return replacementMethod;
}

或者借助TypeScript内置类型工具,明确约束替换函数的类型:

export function loggedMethod<Fn extends (this: any, ...args: any[]) => any>(
  target: Fn,
  context: ClassMethodDecoratorContext<ThisParameterType<Fn>, Fn>
) {
  const methodName = String(context.name);
  const replacementMethod = function(this: ThisParameterType<Fn>, ...args: Parameters<Fn>): ReturnType<Fn> {
    console.log(`LOG : Entering Method "${methodName}"`);
    const result = target.call(this, ...args);
    console.log(`LOG : Exiting Method "${methodName}"`);
    return result;
  };

  return replacementMethod as Fn;
}

以上两种方式都能让TypeScript正确识别替换函数的返回类型,匹配原异步方法的Promise类型,消除错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 13:35:13