microsoft / microsoft/TypeScript
[decorator metadata] implicit runtime reference created
@rbuckton is already working on this.
Since Feb 12, 2021.
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.3k
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 132
Description
Bug Report
🔎 Search Terms
decorator metadata shadow same name generic
(also searched in the "Domain: Decorators" tag)
🕗 Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about decorators
⏯ Playground Link
Playground link with relevant code
💻 Code
import { Test } from './Test';
declare function deco(..._param: any): any;
export class Clazz {
@deco
method<Test>(Test: Test) {
}
}
🙁 Actual behavior
As far as TS's unused vars logic is concerned - the above code just creates a type reference on the generic Test:

However when you look at the generated code:
__decorate([
deco,
__metadata("design:type", Function),
__metadata("design:paramtypes", [typeof (_a = typeof Test !== "undefined" && Test) === "function" ? _a : Object]),
__metadata("design:returntype", void 0)
], Clazz.prototype, "method", null);
The decorator actually creates an implicit value reference on the import Test.
Which means if you want to satisfy the noUnusedLocals error, you will (unknowingly) change the runtime behaviour.
🙂 Expected behavior
I think this is the intended behaviour? TBH I'm not entirely sure.
I haven't found any docs about how it's supposed to work.
I think it should not be generating any runtime references.
__decorate([
deco,
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], Clazz.prototype, "method", null);
For context, in @typescript-eslint we have a scope analyser which also attempts to understand the runtime value references created by emitDecoratorMetadata. This understanding means lint rules like no-unused-vars and consistent-type-imports can understand the runtime code and provide correct lints/fixes. This logic was particularly added for consistent-type-imports, which broke people's code due to it not understanding that decorators created implicit value references.
A user presented a bug due to an (incorrect reference) - https://github.com/typescript-eslint/typescript-eslint/issues/2994.
Whilst investigating the fix, I want to ensure it's fixed correctly for all cases, including the one presented above.
If it's entirely intentional that this creates a value reference - then I'll make the referencer work the same way.
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.
Assessment
This issue has not been assessed yet.