TypeScript中TypedPropertyDecorator泛型异常行为及修复方案
问题原因
TypeScript 对变量赋值和装饰器参数的类型安全校验逻辑存在差异:
- 变量赋值场景:
const test: Test = method是安全的——Test类型允许返回Promise<void | Message>,而method返回更具体的Promise<Message>(属于前者的子类型),符合协变规则,因此不会报错。 - 装饰器场景:装饰器接收
TypedPropertyDescriptor<Test>意味着它可能会替换原方法为一个返回Promise<void | Message>的函数(比如返回void)。但类方法被定义为返回Promise<Message>,调用者会期望得到Message类型值,若装饰器替换后返回void就会破坏类型安全。因此 TypeScript 禁止这种潜在不安全的赋值,触发类型错误。
修复方法
推荐使用泛型装饰器,既保留类型安全,又允许方法返回更具体的类型:
type Message = { Body: string }; type Test = (message: Message) => Promise<void | Message>; // 此处无类型错误 const test: Test = async (message: Message) => ({ Body: 'hey' }); // 泛型装饰器,约束方法类型兼容 Test const a = <T extends Test>(target: object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => { const og = descriptor.value; console.log('Hey') }; class A { @a // 不再报错 public async method(message: Message): Promise<Message> { return message; } }
其他可选方案:
- 放宽类方法的返回类型为
Promise<void | Message>,与Test类型完全匹配; - 直接将装饰器的参数类型改为
TypedPropertyDescriptor<(message: Message) => Promise<Message>>,但会限制装饰器只能用于返回Message的方法。
内容的提问来源于stack exchange,提问作者Alessandro Commodari
相关产品推荐
相关产品推荐

