如何让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; } }
原理说明
- 装饰器工厂函数先接收
options,但不立即推导泛型; - 内部函数接收被装饰方法的类型
T,通过ExtractReturnType工具类型提取其返回类型; - 强制将
options.returnValue断言为方法返回类型,若类型不匹配,TypeScript会直接抛出错误; - 泛型推导优先级完全由被装饰方法的返回类型主导,无需显式指定泛型参数。
内容的提问来源于stack exchange,提问作者seabeast
相关产品推荐
相关产品推荐

