使用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
相关产品推荐
相关产品推荐

