microsoft / microsoft/TypeScript

Reflect Metadata not supported for TC39 decorators

オープン
#55,788 コメント 9 件 リアクション 19 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

Awaiting More Feedback Suggestion
主要言語
Go
スター
111k
フォーク
14.4k
平均マージ
1日 19時間
マージ済み PR(30日)
117

説明

🔎 Search Terms

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

🕗 Version & Regression Information

This breaks when setting disabling experimental decorators

"experimentalDecorators": false,
"emitDecoratorMetadata": false,
⏯ Playground Link

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

💻 Code

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();

run with:

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

Reflect.getMetadata('design:type', target, property) returns undefined.

🙂 Expected behavior

Reflect.getMetadata('design:type', target, property) returns the type of the class field, when using Standard TC39 decorators.

Additional information about the issue
  1. When transpiling with:

    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    

    The decorator Reflect.metadata("design:type", type) is automatically applied to each class field.

  2. When transpiling with:

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

    The decorator Reflect.metadata("design:type", type) is not applied.

  3. When transpiling with:

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

    Typescript produces the following error

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

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

リンクされた playground から tsc --project tsconfig.json && node dist/index.js を実行し、次に src/index.ts とその decorator 呼び出し、および tsconfig.json から調査を始めてください。標準の TC39 decorator パスが、Reflect.getMetadata('design:type', ...) を通じて undefined ではなくクラスフィールドの型を返し、報告されているコンパイラーオプションの制約を変更しなければ完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
typescript
領域
compilers
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
45/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。