reflect-metadata and Design Types
Capture parameter and property types at runtime.
reflect-metadata and Design Types is a free TypeScript Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the TypeScript Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
reflect-metadata and Design Types
Before standardized metadata existed, TypeScript could emit design-time type information at runtime via the reflect-metadata library plus the emitDecoratorMetadata compiler flag. This lesson covers that older but still widely used mechanism.
Enabling the Feature
Two things are required: turn on the compiler options and import the library once at the program entry point.
// tsconfig.json
// {
// "compilerOptions": {
// "experimentalDecorators": true,
// "emitDecoratorMetadata": true
// }
// }
import "reflect-metadata";What Gets Emitted
With emitDecoratorMetadata, the compiler emits three keys for decorated members: design:type, design:paramtypes, and design:returntype. The values are the constructor functions (e.g. String, Number).
Reading design:type
For a decorated property, Reflect.getMetadata("design:type", target, key) returns the property type constructor.
import "reflect-metadata";
function track(target: any, key: string) {
const t = Reflect.getMetadata("design:type", target, key);
console.log(key, "->", t.name); // e.g. "name -> String"
}
class Person {
@track name!: string;
@track age!: number;
}Reading design:paramtypes
On a constructor or method, design:paramtypes is an array of the parameter type constructors, the foundation of dependency injection.
function injectable(target: any) {
const params = Reflect.getMetadata("design:paramtypes", target);
console.log(params.map((p: any) => p.name)); // ["Database", "Logger"]
}
@injectable
class Service {
constructor(private db: Database, private log: Logger) {}
}Limitations of Emitted Types
Only simple, runtime-representable types survive. Interfaces, unions, and generics collapse to Object because they have no runtime constructor. Design types are approximate, not the full TS type.
Custom Metadata With Reflect
You can also define your own metadata keys with Reflect.defineMetadata, independent of design types.
import "reflect-metadata";
function required(target: any, key: string) {
Reflect.defineMetadata("required", true, target, key);
}
function isRequired(target: any, key: string) {
return Reflect.getMetadata("required", target, key) === true;
}Where It Is Used
This mechanism powers many established frameworks (NestJS, TypeORM, class-validator). They read design:type and design:paramtypes to wire dependencies and validate values without you restating types.
reflect-metadata vs Standard Metadata
The new Symbol.metadata API is part of the language and does not emit design types. reflect-metadata uniquely provides type info but is tied to the experimental decorator mode. Pick one model per project.
Import Order Matters
import "reflect-metadata" must run once, before any decorated class is evaluated, because it patches the global Reflect object with the metadata functions. Import it at the very top of your entry file.
Why It Matters
Emitting design types lets frameworks bridge the gap between compile-time types and runtime behavior, the key enabler for ergonomic DI and validation. Knowing its limits (no interfaces, no generics) prevents surprising Object results.
Quick Check
Test your understanding of reflect-metadata.
Recap
With experimentalDecorators + emitDecoratorMetadata and an early import "reflect-metadata", the compiler emits design:type and design:paramtypes as runtime constructors. Frameworks read these for DI and validation, though interfaces/unions/generics degrade to Object.
Frequently asked questions
Is the “reflect-metadata and Design Types” lesson free?
Yes — the full text of “reflect-metadata and Design Types” is free to read here on the web, and the TypeScript Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the TypeScript Academy course, upgrade to CoddyKit PRO.
What will I learn in “reflect-metadata and Design Types”?
Capture parameter and property types at runtime. You practise TypeScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start TypeScript Academy?
No prior experience is required. TypeScript Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “reflect-metadata and Design Types” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this TypeScript Academy lesson?
Yes. Every TypeScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Stage 3 Decorators Explained
- Decorator Metadata
- reflect-metadata and Design Types
- Building a Decorator Framework