正如@cdimitroulas 所说,这是不可能的,装饰器不会改变 Typescript 类型。
不过,我们可以解决您的一些问题:
// 这个返回有什么问题?
const task = (
target: unknown,
propertyKey: string,
// you said here that descriptor is this type
descriptor: TypedPropertyDescriptor<(...args: unknown[]) => unknown>,
// yet, you said that the type is different here, namely that the first argument is of type string (it was unknown)
): TypedPropertyDescriptor<(name: string, ...args: unknown[]) => unknown> => {
const original = descriptor.value
descriptor.value = function (...args: unknown[]) {
return original?.call(this, 'Mark', ...args)
}
// you're returning the same descriptor that was passed to the decorator
return descriptor
}
Typescript 期望找到相同的类型,但它是不同的,因此它会尝试比较它们以查看一个是否可以分配给另一个,但事实并非如此。 unknown 不能分配给 string。 unknown 只能分配给 unknown 或 any。
知道装饰器无论如何都不会改变类型,你可以完全省略返回类型,让 Typescript 为你推断
const task = (
target: unknown,
propertyKey: string,
descriptor: TypedPropertyDescriptor<(...args: unknown[]) => unknown>,
) => {
const original = descriptor.value
descriptor.value = function (...args: unknown[]) {
return original?.call(this, 'Mark', ...args)
}
return descriptor
}
接下来,Typescript 仍然对此不满意:
@task // --> Type '(name: string) => void' is not assignable to type '(...args: unknown[]) => unknown'
printName(name: string) {
console.log(name)
}
如前所述,unknown 不能分配给string。因此,要么将unknown 更改为any(不安全),要么将签名更改为TypedPropertyDescriptor<(name: string) => void>
const task = (
target: any,
propertyKey: string,
descriptor: TypedPropertyDescriptor<(name: string) => void>,
) => {
const original = descriptor.value
descriptor.value = function () {
return original?.call(this, 'Mark')
}
return descriptor
}
至于这一行
this.printName()
您能做的最好的事情就是将 name 属性设为可选。装饰者基本上是在为我们设置道具,所以在这种情况下,我们可以完全移除道具,尽管我知道这不是一个真实的案例,只是一个例子来说明你的观点。