microsoft / microsoft/TypeScript
Reflect Metadata not supported for TC39 decorators
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.3k
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 117
Description
🔎 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
-
When transpiling with:
"experimentalDecorators": true, "emitDecoratorMetadata": true,The decorator
Reflect.metadata("design:type", type)is automatically applied to each class field. -
When transpiling with:
"experimentalDecorators": false, "emitDecoratorMetadata": false,The decorator
Reflect.metadata("design:type", type)is not applied. -
When transpiling with:
"experimentalDecorators": false, "emitDecoratorMetadata": true,Typescript produces the following error
Option 'emitDecoratorMetadata' cannot be specified without specifying option 'experimentalDecorators'.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Run tsc --project tsconfig.json && node dist/index.js from the linked playground, then start with src/index.ts and its decorator calls alongside tsconfig.json. Done means the standard TC39 decorator path returns the class-field type through Reflect.getMetadata('design:type', ...) rather than undefined, without changing the reported compiler-option constraints.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100