如何使泛型方法装饰器foo适配MethodDecorator类型?
The error you're encountering stems from a mismatch between your explicit generic constraint and TypeScript's built-in MethodDecorator type signature. Let's break down the issue and fix it properly.
Why the Error Happens
TypeScript defines MethodDecorator as a generic function that works with any type T (representing the decorated method):
type MethodDecorator = <T>( target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T> ) => TypedPropertyDescriptor<T> | void;
Your original code added an explicit T extends Function = Function constraint to the decorator function, which conflicts with MethodDecorator's unconstrained generic T. TypeScript can't reconcile the constrained T in your function with the generic expected by the standard MethodDecorator type.
Solution: Align with MethodDecorator's Generic Signature
You don't need to manually constrain T—since this is a method decorator, TypeScript will automatically infer that T is a function type. Here's the corrected code:
const foo: MethodDecorator = function <T>( target: object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T> ): TypedPropertyDescriptor<T> { // Defensive check to ensure we're decorating a method if (typeof descriptor.value !== 'function') { throw new Error('The foo decorator can only be applied to class methods'); } // Bind the method to null while preserving its original type return { configurable: true, enumerable: false, value: descriptor.value.bind(null) as T }; };
Key Adjustments:
- Removed the explicit
T extends Function = Functionconstraint to matchMethodDecorator's native generic signature. - Added a runtime check to confirm
descriptor.valueis a function (prevents misuse on non-method properties). - Used
as Tto assert the bound function matches the original method's type—this is safe becausebindpreserves the function's signature (only overriding thethiscontext tonull).
Simplified Version (Without Runtime Check)
If you're certain the decorator will only be used on methods, you can streamline the code with a type assertion:
const foo: MethodDecorator = function <T>( target: object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T> ): TypedPropertyDescriptor<T> { const originalMethod = descriptor.value as unknown as Function; return { configurable: true, enumerable: false, value: originalMethod.bind(null) as T }; };
This works because TypeScript trusts that you're applying the decorator to a method, so T will always be a function type in practice.
内容的提问来源于stack exchange,提问作者Estus Flask

