I am trying to get the response type of the method to which I assign a decorator (an old-style TypeScript experimental decorator, not the newer JS decorators). This is to use the name of the properties of the response as parameters inside the decorator itself.
I have the following code:
type TaskProps<T, M> = {
next: keyof T;
param: ReturnType<M> extends {} ? keyof ReturnType<M> : string;
};
function Task<T, K extends keyof T>(props: TaskProps<T, T[K]>) {
return function (target: T, propertyKey: K, descriptor: PropertyDescriptor) {
};
}
class ExampleClass {
@Task({
next: "bye",
param: "name",
})
hello() {
return {
name: "example",
age: 11
};
}
bye() {}
}
When I pass the type M to the ReturnType, it tells me that
Type 'M' does not satisfy the constraint '(...args: any) => any'.
In what follows I'm not going to really touch on the whole topic of decorators in TypeScript, such as the differences between TypeScript experimental decorators (which you're using here) and newer JavaScript decorators (which you're not), or whether your decorator function actually does what you want. I'm only concerned here with clearing up the compiler error you are asking about.
The error Type 'M' does not satisfy the constraint '(...args: any) => any'.
means that the generic type parameter M
is not constrained to a function type. It might be anything at all (like string
, or Date
). But the ReturnType
utility type requires its type argument to be a function type. The easiest fix here is therefore to constrain M
accordingly:
type TaskProps<T, M extends (...args: any) => any> = {
next: keyof T;
param: ReturnType<M> extends {} ? keyof ReturnType<M> : string; // okay
};
And then you'll want to propagate that constraint to Task
, possibly like this"
function Task<
T extends Record<K, (...args: any) => any>,
K extends keyof T
>(props: TaskProps<T, T[K]>) {
return function (target: T, propertyKey: K, descriptor: PropertyDescriptor) {
};
}
Here we're saying (with the Record
utility type) that T
is known to have a key of type K
whose property value is a function type, which lets the compiler conclude that the indexed access type T[K]
is suitable for the second type argument to TaskProps
and thus as a type argument to ReturnType
.