typescript - 如何在 TS 中输入装饰器

标签 typescript

我想知道如何正确输入method decorators在 typescript 中。我有一个简单的装饰器,它将字符串参数作为第一个参数添加到装饰函数中。它工作得很好,问题是我不知道如何正确输入它以及它是否可能?

const task = (
  target: unknown,
  propertyKey: string,
  descriptor: TypedPropertyDescriptor<(...args: unknown[]) => unknown>,
): TypedPropertyDescriptor<(name: string, ...args: unknown[]) => unknown> => {
  const original = descriptor.value
  descriptor.value = function (...args: unknown[]) {
    return original?.call(this, 'Mark', ...args)
  }

  // what's wrong with this return?
  return descriptor
}



class Test {

    constructor(){
      // should not report an error
      this.printName()
    }


    @task
    printName(name: string) {
        console.log(name)

    }

}


  new Test()

Playground 可用 here

最佳答案

正如 @cdimitroulas 所说,这是不可能的,装饰器不会改变 Typescript 类型。

不过,我们可以解决您的一些问题:

// what's wrong with this return?

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不可分配给stringunknown只能分配给 unknownany 。 知道装饰器无论如何都不会更改类型,您可以完全省略返回类型并让 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 。所以要么我们改变unknownany (不安全)或者更好的是,我们将签名更改为 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 属性成为可选的。装饰器基本上是为我们设置 Prop ,所以在这种情况下,我们可以完全删除 Prop ,尽管我知道这不是一个真实的案例,只是一个例子来说明你的观点。

关于typescript - 如何在 TS 中输入装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67055899/

相关文章:

javascript - 如何一次性获取BehaviorSubject的当前值?

javascript - Angular 中的 Foreach 对象

javascript - 过滤器不是创建一个新数组吗?

javascript - 如何将IIFE包裹的JS文件导入TS

debugging - 如何在 Visual Studio Code 中调试 Angular2 TypeScript 应用程序?

javascript - 无法在 Angular 2 组件中连接字符串

javascript - 更改管道中对象的属性(rxjs)

javascript - 如何将字符串推送到 typescript 数组?

angular - 为什么 Angular HttpRequest 添加私有(private)属性到 url?

typescript - Visual Studio 指定定义文件