英文:
Return type is not assignable to unknown using TypeScript 5 decorators
问题
尝试实现新的TypeScript 5装饰器,但我面临一个我不理解的类型问题。下面是一个简单的示例,TS PLAYGROUND HERE
错误信息如下:
装饰器函数的返回类型'(this: ProductsService, ...args: any[]) => unknown'无法分配给类型'void | ((mockProducts: any) => Promise<TProductsDtoOutput[]>)'。
类型'(this: ProductsService, ...args: any[]) => unknown'无法分配给类型'(mockProducts: any) => Promise<TProductsDtoOutput[]>'。
类型'unknown'无法分配给类型'Promise<TProductsDtoOutput[]>'。
export function loggedMethod<This, Args extends any[], Return, Fn extends (this: This, ...args: Args) => Return>(
target: Fn,
context: ClassMethodDecoratorContext<This, Fn>
) {
const methodName = String(context.name);
function replacementMethod(this: This, ...args: Args): Return {
console.log(`LOG : 进入方法 "${methodName}"`);
const result = target.call(this, ...args);
console.log(`LOG : 退出方法 "${methodName}"`);
return result;
}
return replacementMethod;
}
type TProductsDtoOutput = {
all: string;
}
export class ProductsService {
@loggedMethod
async getAll(mockProducts: any): Promise<TProductsDtoOutput[]> {
const result = mockProducts.map((product: any) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { id, ...rest } = product;
return rest as TProductsDtoOutput;
});
return result;
}
}
英文:
Trying to implement the new TypeScript 5 decorators, but I'm facing a typing issue that I do not understand.
Below is the simple example, TS PLAYGROUND HERE
Error is:
>
> Decorator function return type '(this: ProductsService, ...args: any[]) => unknown' is not assignable to type 'void | ((mockProducts: any) => Promise<TProductsDtoOutput[]>)'.
> Type '(this: ProductsService, ...args: any[]) => unknown' is not assignable to type '(mockProducts: any) => Promise<TProductsDtoOutput[]>'.
> Type 'unknown' is not assignable to type 'Promise<TProductsDtoOutput[]>'.
>
export function loggedMethod<This, Args extends any[], Return, Fn extends (this: This, ...args: Args) => Return>(
target: Fn,
context: ClassMethodDecoratorContext<This, Fn>
) {
const methodName = String(context.name);
function replacementMethod(this: This, ...args: Args): Return {
console.log(`LOG : Entering Method "${methodName}"`);
const result = target.call(this, ...args);
console.log(`LOG : Exiting Method "${methodName}"`);
return result;
}
return replacementMethod;
}
type TProductsDtoOutput = {
all:string
}
export class ProductsService {
@loggedMethod
async getAll(mockProducts:any): Promise<TProductsDtoOutput[]> {
const result = mockProducts.map((product:any) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { id, ...rest } = product;
return rest as TProductsDtoOutput;
});
return result
}
}
答案1
得分: 1
TS在这种情况下不会自动推断第一个泛型参数。请手动推断,然后这将起作用。
export function loggedMethod<Fn extends (...args: any[]) => any>(
target: Fn,
context: ClassMethodDecoratorContext<ThisParameterType<Fn>, Fn>
) {
const methodName = String(context.name);
return function replacementMethod(this: ThisParameterType<Fn>, ...args: Parameters<Fn>) {
console.log(`LOG : 进入方法 "${methodName}"`);
const result = target.call(this, ...args);
console.log(`LOG : 离开方法 "${methodName}"`);
return result;
}
}
英文:
TS does not infer first generics in this case. Infer them manually then this will work.
export function loggedMethod<Fn extends (...args: any[]) => any>(
target: Fn,
context: ClassMethodDecoratorContext<ThisParameterType<Fn>, Fn>
) {
const methodName = String(context.name);
return function replacementMethod(this: ThisParameterType<Fn>, ...args: Parameters<Fn>) {
console.log(`LOG : Entering Method "${methodName}"`);
const result = target.call(this, ...args);
console.log(`LOG : Exiting Method "${methodName}"`);
return result;
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论