TypeScript 5中非静态属性装饰器的签名是什么?

pn9klfpd  于 2023-04-07  发布在  TypeScript
关注(0)|答案(1)|浏览(118)

虽然TypeScript 5已经正式实现了新的装饰器,但装饰器文档仍然是关于TypeScript 4的装饰器(2023年4月1日)。

装饰器函数的签名已经改变。实验中我有两个参数,第一个是undefined,第二个是类似元数据的:

export default function VueReactiveDataField(
  ...blackBoxes: Array<unknown>
): void {

  console.log(blackBoxes);

  // ...

}

@VueComponentOptions
export default class ReactiveStateExperimentalSample {

  @VueReactiveDataField
  protected exampleReactiveField: string = "Experimental sample works fine";

}

控制台输出为:

它们的类型是什么,为什么第一个是undefined?

[附录] tsconfig.json

当然不是"experimentalDecorators": true

{
  "compilerOptions": {

    "target": "ES2020",
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,

    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": false, /* Actual for Vue3; see https://github.com/vuejs/vue-next/issues/4668 */
    "allowJs": true, /* Actual for Vue3; */
    "skipLibCheck": true,

    "baseUrl": "./",
    "paths": {
      "@Source/*": [ "./Source/*" ]
    },
    "declaration": true
  },
  "include": [
    "Project.d.ts",
    "Source/**/*",
    "Tests/**/*"
  ]
}
kpbpu008

kpbpu0081#

你可以在ECMAScript decorators proposal中阅读有关decorators的内容。特别是对于类字段decorators,第一个参数总是undefined。对于第二个参数,TS5提供了ClassFieldDecoratorContext<This, Value> helper类型。
举个例子

function VueReactiveDataField(
  _: undefined,
  // `unknown` if you don't care about the type of the class where decorated
  // property belongs
  // `string` so that you can only decorate string properties
  context: ClassFieldDecoratorContext<unknown, string>
): void {
  console.log(_, context);
}

@VueComponentOptions
export default class ReactiveStateExperimentalSample {
  @VueReactiveDataField
  protected exampleReactiveField: string = "Experimental sample works fine";
}

或者让它通用化

function VueReactiveDataField<
  This, 
  // Will only work for properties of type `string`, `number` or `string | number` (or `never` but that's boring)
  Value extends string | number
>(
  _: undefined,
  context: ClassFieldDecoratorContext<This, Value>
): void {
  console.log(_, context);
}

@VueComponentOptions
export default class ReactiveStateExperimentalSample {
  @VueReactiveDataField
  protected exampleReactiveField: string = "Experimental sample works fine";
}

相关问题