I tried to implement a decorator in typescript that can only be applied to async functions. If the decorator is applied to a none async function the compile should raise an error.
Here is what I tried so far:
type AsyncFunction = (...args: any[]) => Promise<any>
function MyDecorator(/* params as needed */) {
return function <P extends string>(target: Record<P, AsyncFunction> , propertyKey: P) {
console.log("Implementation of MyDecorator")
}
}
class SomeClassWithPrivateMethod {
@MyDecorator()
private async somePrivateMethod() {
}
@MyDecorator()
async somePublicMethod() {
}
}
The problem is, that it does not work for private methods with the following error message:
Argument of type 'SomeClassWithPrivateMethod' is not assignable to parameter of type 'Record<"somePrivateMethod", AsyncFunction>'.
Property 'somePrivateMethod' is private in type 'SomeClassWithPrivateMethod' but not in type 'Record<"somePrivateMethod", AsyncFunction>'.
What do I have to change to make it work for private methods?
For my use case I found a very simple solution
- tested with typescript 4.6.3 -
Instead of applying a contraint to the target parameter, it is possible restrict the descriptor parameter to a specific type:
type AsyncFunction = (...args: any[]) => Promise<any>
function MyDecorator(/* params as needed */) {
return function(target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<AsyncFunction>) {
console.log("Implementation of MyDecorator")
}
}
TypedPropertyDescriptor<AsyncFunction>
is the key here. TypedPropertyDescriptor
is a built in type from typescript.