Decorators & Metadata Interview Questions
Comprehensive decorators & metadata interview questions and answers for TypeScript. Prepare for your next job interview with expert guidance.
Questions Overview
1. What are decorators in TypeScript and how do you enable them?
Basic2. What are the different types of decorators in TypeScript?
Basic3. How do you create and use class decorators?
Moderate4. How do method decorators work in TypeScript?
Moderate5. What is reflect-metadata and how is it used with decorators?
Advanced6. How do property decorators differ from method decorators?
Moderate7. What are decorator factories and how do you create them?
Advanced8. How do you implement parameter decorators?
Advanced9. What are accessor decorators and when should you use them?
Advanced10. How do you combine multiple decorators?
Moderate11. What is the role of metadata in TypeScript decorators?
Advanced12. How do you implement validation using decorators?
Advanced13. What are the common use cases for decorators?
Moderate14. How do you use decorators for dependency injection?
Advanced15. What are the limitations of decorators in TypeScript?
Advanced16. How do you implement memoization using decorators?
Advanced17. What is design-time type metadata and how is it used?
Advanced18. How do you implement method overriding detection using decorators?
Advanced19. What are the best practices for using decorators?
Moderate20. How do you implement lazy initialization using decorators?
Advanced21. How do you handle async operations in decorators?
Advanced22. What are the differences between ES decorators and TypeScript decorators?
Advanced1. What are decorators in TypeScript and how do you enable them?
BasicDecorators are special declarations that can be attached to class declarations, methods, properties, or parameters. They are enabled by setting 'experimentalDecorators: true' in tsconfig.json. Example: @decorator class Example {}. Decorators provide a way to add annotations and metadata to existing code.
2. What are the different types of decorators in TypeScript?
BasicTypeScript supports five types of decorators: 1) Class decorators (@classDecorator), 2) Method decorators (@methodDecorator), 3) Property decorators (@propertyDecorator), 4) Accessor decorators (@accessorDecorator), and 5) Parameter decorators (@parameterDecorator). Each type receives different arguments and can be used for different purposes.
3. How do you create and use class decorators?
ModerateClass decorators are declared before a class declaration and receive the constructor as an argument. Example: function logger(target: Function) { console.log(`Creating class: ${target.name}`); } @logger class Example {}. They can modify or replace the class definition and are useful for adding metadata or behavior to classes.
4. How do method decorators work in TypeScript?
ModerateMethod decorators are declared before method declarations and receive three arguments: target (prototype), propertyKey (method name), and descriptor (property descriptor). Example: function log(target: any, key: string, descriptor: PropertyDescriptor) { // Original method const original = descriptor.value; descriptor.value = function(...args: any[]) { console.log(`Calling ${key}`); return original.apply(this, args); }; }
5. What is reflect-metadata and how is it used with decorators?
Advancedreflect-metadata is a library that adds a polyfill for the Metadata Reflection API. It's used with decorators to add and read metadata about classes, methods, and properties. Enable with 'emitDecoratorMetadata: true' in tsconfig.json. Example: import 'reflect-metadata'; @Reflect.metadata('role', 'admin') class User {}
6. How do property decorators differ from method decorators?
ModerateProperty decorators receive two arguments: target (prototype) and propertyKey (property name), unlike method decorators which also receive a descriptor. Example: function validate(target: any, key: string) { let value = target[key]; Object.defineProperty(target, key, { get: () => value, set: (newValue) => { if (!newValue) throw new Error('Value cannot be null'); value = newValue; } }); }
7. What are decorator factories and how do you create them?
AdvancedDecorator factories are functions that return decorators and allow customization through parameters. Example: function log(prefix: string) { return function(target: any) { console.log(`${prefix}: ${target.name}`); }; } @log('MyApp') class Example {}. They provide a way to customize decorator behavior.
8. How do you implement parameter decorators?
AdvancedParameter decorators are applied to method parameters and receive three arguments: target (prototype), methodName, and parameterIndex. Example: function required(target: Object, propertyKey: string, parameterIndex: number) { const requiredParams = Reflect.getMetadata('required', target, propertyKey) || []; requiredParams.push(parameterIndex); Reflect.defineMetadata('required', requiredParams, target, propertyKey); }
9. What are accessor decorators and when should you use them?
AdvancedAccessor decorators are applied to getter/setter declarations and receive three arguments similar to method decorators. Example: function enumerable(value: boolean) { return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) { descriptor.enumerable = value; }; } They're useful for modifying accessor behavior.
10. How do you combine multiple decorators?
ModerateMultiple decorators can be applied to a declaration in sequence. They are evaluated in reverse order (bottom to top). Example: @f @g class C {}. Evaluation order: g then f. For decorator factories: @f() @g() class C {}, the factories are evaluated in order (f then g) but the decorators in reverse order.
11. What is the role of metadata in TypeScript decorators?
AdvancedMetadata allows storing additional information about classes, methods, and properties that can be accessed at runtime. It's enabled with reflect-metadata. Example: Reflect.defineMetadata('validation', { required: true }, target, propertyKey); const metadata = Reflect.getMetadata('validation', target, propertyKey);
12. How do you implement validation using decorators?
AdvancedValidation decorators can be implemented using property or parameter decorators with metadata. Example: function required(target: any, propertyKey: string) { const validationMetadata = { required: true }; Reflect.defineMetadata('validation', validationMetadata, target, propertyKey); } class User { @required name: string; }
13. What are the common use cases for decorators?
ModerateCommon use cases include: 1) Logging and monitoring, 2) Property validation, 3) Dependency injection, 4) Method memoization, 5) Access control and authorization, 6) Class and property transformation, 7) API endpoint definition (e.g., in NestJS), 8) Observable properties (e.g., in Angular), 9) Type serialization/deserialization.
14. How do you use decorators for dependency injection?
AdvancedDecorators can implement dependency injection by using metadata to store and retrieve dependencies. Example: function Injectable() { return function(target: any) { Reflect.defineMetadata('injectable', true, target); }; } @Injectable() class Service {} This pattern is used in frameworks like Angular and NestJS.
15. What are the limitations of decorators in TypeScript?
AdvancedLimitations include: 1) Experimental feature requiring compiler flag, 2) Can't decorate declarations in .d.ts files, 3) Limited to specific declaration types (class, method, property, parameter), 4) Can't access decorated values during declaration phase, 5) No direct way to decorate local variables or function declarations.
16. How do you implement memoization using decorators?
AdvancedMemoization decorators cache function results based on arguments. Example: function memoize(target: any, key: string, descriptor: PropertyDescriptor) { const original = descriptor.value; const cache = new Map(); descriptor.value = function(...args: any[]) { const key = JSON.stringify(args); if (cache.has(key)) return cache.get(key); const result = original.apply(this, args); cache.set(key, result); return result; }; }
17. What is design-time type metadata and how is it used?
AdvancedDesign-time type metadata is automatically generated when emitDecoratorMetadata is enabled. It includes type information for parameters, return types, and properties. Example: const paramTypes = Reflect.getMetadata('design:paramtypes', target, key); This is used by frameworks for dependency injection and validation.
18. How do you implement method overriding detection using decorators?
AdvancedMethod override decorators can verify proper method overriding. Example: function override(target: any, key: string, descriptor: PropertyDescriptor) { const baseClass = Object.getPrototypeOf(target); if (!baseClass[key]) throw new Error(`${key} doesn't override any base method`); return descriptor; } class Child extends Parent { @override method() {} }
19. What are the best practices for using decorators?
ModerateBest practices include: 1) Use decorator factories for configuration, 2) Keep decorators focused and single-purpose, 3) Handle errors gracefully, 4) Use meaningful names that describe behavior, 5) Document decorator requirements and effects, 6) Avoid side effects in decorator evaluation, 7) Use metadata for storing configuration, 8) Consider performance implications.
20. How do you implement lazy initialization using decorators?
AdvancedLazy initialization decorators delay property initialization until first access. Example: function lazy<T>(initializer: () => T) { return function(target: any, key: string) { let value: T; Object.defineProperty(target, key, { get: () => { if (!value) value = initializer(); return value; } }); }; } class Example { @lazy(() => expensiveOperation()) value: string; }
21. How do you handle async operations in decorators?
AdvancedAsync operations in decorators require special handling since decorators run during class definition. Example: function asyncInit() { return function(target: any) { return class extends target { async init() { await super.init(); // Additional async initialization } }; }; } @asyncInit() class Service { async init() { /* ... */ } }
22. What are the differences between ES decorators and TypeScript decorators?
AdvancedKey differences include: 1) Syntax variations, 2) TypeScript decorators are experimental while ES decorators are part of the standard, 3) Different metadata handling, 4) ES decorators have additional capabilities like decorating object literals, 5) TypeScript decorators may need updates to align with ES decorator standard when finalized.