TypeScript 对于TC39装饰器,不支持Reflect Metadata,

ykejflvf  于 6个月前  发布在  TypeScript
关注(0)|答案(7)|浏览(57)

🔎 搜索词

decorator, experimentalDecorators, emitDecoratorMetadata, TC39, reflect-metadata, Reflect.metadata(k, v)

🕗 版本与回归信息

当设置禁用实验性装饰器时出现问题

"experimentalDecorators": false,
"emitDecoratorMetadata": false,

⏯ Playground链接

https://github.com/paulsmithkc/typescript-decorators

💻 代码

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2021",
    "module": "commonjs",
    "outDir": "dist",
    "declaration": true,
    "experimentalDecorators": false,
    "emitDecoratorMetadata": false
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}

src/index.ts

import 'reflect-metadata';

function setting(defaultValue: string): any {
  function getType(target: unknown, property: string | symbol) {
    return Reflect.getMetadata('design:type', target, property);
  }
  function settingExperimental(target: unknown, property: string | symbol): void {
    console.log('settingExperimental', { defaultValue, target, property, type: getType(target, property) });
    target[property] = process.env[String(property)] || defaultValue;
    return;
  }
  function settingTC39(_target: unknown, context: ClassFieldDecoratorContext): () => string {
    return function (): string {
      console.log('settingTC39', { defaultValue, target: this, context, type: getType(this, context.name) });
      return process.env[String(context.name)] || defaultValue;
    };
  }
  return function (target: unknown, context: string | symbol | ClassFieldDecoratorContext) {
    if (typeof context !== 'object') {
      return settingExperimental(target, context);
    } else {
      return settingTC39(target, context);
    }
  };
}

class Config {
  @setting('default_1') SETTING_ONE: string;
}
const configInstance = new Config();

运行方式:

tsc --project tsconfig.json && node dist/index.js

🙁 实际行为

Reflect.getMetadata('design:type', target, property) 返回 undefined。

🙂 预期行为

Reflect.getMetadata('design:type', target, property) 在使用标准 TC39 装饰器时,返回类字段的类型。

关于问题的附加信息

  1. 使用以下方式进行转译时:
"experimentalDecorators": true,
"emitDecoratorMetadata": true,

装饰器 Reflect.metadata("design:type", type) 会自动应用于每个类字段。

  1. 使用以下方式进行转译时:
"experimentalDecorators": false,
"emitDecoratorMetadata": false,

装饰器 Reflect.metadata("design:type", type) 不会被应用。

  1. 使用以下方式进行转译时:
"experimentalDecorators": false,
"emitDecoratorMetadata": true,

Typescript 产生以下错误

Option 'emitDecoratorMetadata' cannot be specified without specifying option 'experimentalDecorators'.
vyu0f0g1

vyu0f0g11#

据我所知,这个功能尚未实现。请参阅 #53461

zd287kbt

zd287kbt2#

同样的问题。许多库使用关于类型的元数据,例如Angular、NestJs、class-validator和用于依赖注入的我的库。为新的装饰器生成元数据是非常必要的。

c0vxltue

c0vxltue3#

我也遇到了这个问题。这里是操场链接。
我已经将 emitDecoratorMetadata 设置为 true ,但发射的代码中不包含 desgin:type 元数据。

z9smfwbn

z9smfwbn4#

我认为这个问题的标题需要改成类似于TC39 Decorators does not emit metadata to Symbol.Metadata这样的内容。同时,查看代码后发现它似乎没有在这里实现:https://github.com/microsoft/TypeScript/blob/v5.3.3/src/compiler/transformers/ts.ts#L1064

yhuiod9q

yhuiod9q5#

我也认为发射类型元数据是非常必要的,但是现在DecoratorsDecorator Metadata已经在TC39中实现了阶段3,并且在TS >=5.2中得到了实现,因此不再考虑在reflect-metadata库中提出的API进行标准化。这就是为什么我认为更好的是expose design-time type information in the new TC39 decorator metadata when emitDecoratorMetadata: true

watbbzwu

watbbzwu6#

我也认为发射类型元数据是非常必要的,但现在DecoratorsDecorator Metadata已经在TC39中实现了阶段3,并在TS >=5.2中得到了实现,因此不再考虑将reflect-metadata库中提出的API标准化。
这就是为什么我认为最好使用expose design-time type information in the new TC39 decorator metadata when emitDecoratorMetadata: true的原因。
倾向于同意@artberri的意见。我已经为如何实现这一点提出了一个PoC/提案。许多基础已经建立起来,所以这几乎不需要任何更改。

相关问题