0
# Decorators
1
2
Comprehensive decorator system for marking classes as injectable, defining lifecycle behavior, configuring automatic registration, and specifying parameter injection patterns.
3
4
## Capabilities
5
6
### Class Decorators
7
8
Decorators applied to class declarations to mark them for dependency injection and configure registration behavior.
9
10
#### Injectable Decorator
11
12
Marks a class as injectable by storing dependency metadata for constructor parameters.
13
14
```typescript { .api }
15
/**
16
* Marks a class as injectable, enabling constructor injection
17
* @param options - Optional configuration for token registration
18
* @returns Class decorator function
19
*/
20
function injectable<T>(options?: {
21
token?: InjectionToken<T> | InjectionToken<T>[]
22
}): ClassDecorator;
23
```
24
25
**Usage Examples:**
26
27
```typescript
28
// Basic injectable class
29
@injectable()
30
class UserService {
31
constructor(private logger: Logger, private db: Database) {}
32
}
33
34
// Injectable with token specification
35
@injectable({ token: "IUserService" })
36
class UserService implements IUserService {
37
constructor(private logger: Logger) {}
38
}
39
40
// Injectable with multiple tokens
41
@injectable({ token: ["IUserService", "IService"] })
42
class UserService implements IUserService, IService {
43
constructor(private logger: Logger) {}
44
}
45
```
46
47
#### Singleton Decorator
48
49
Registers a class as a singleton in the global container, ensuring only one instance exists.
50
51
```typescript { .api }
52
/**
53
* Registers class as singleton in global container
54
* Automatically registers the class with Lifecycle.Singleton
55
* @returns Class decorator function
56
*/
57
function singleton<T>(): ClassDecorator;
58
```
59
60
**Usage Examples:**
61
62
```typescript
63
@singleton()
64
class ConfigurationService {
65
private config = { apiUrl: "https://api.example.com" };
66
67
getConfig() {
68
return this.config;
69
}
70
}
71
72
// Singleton with injectable
73
@singleton()
74
@injectable()
75
class DatabaseService {
76
constructor(private config: ConfigurationService) {}
77
}
78
```
79
80
#### Scoped Decorator
81
82
Registers a class with specific scoped lifecycle (ContainerScoped or ResolutionScoped).
83
84
```typescript { .api }
85
/**
86
* Registers class with specific scoped lifecycle
87
* @param lifecycle - Must be Lifecycle.ContainerScoped or Lifecycle.ResolutionScoped
88
* @param token - Optional injection token for registration
89
* @returns Class decorator function
90
*/
91
function scoped<T>(
92
lifecycle: Lifecycle.ContainerScoped | Lifecycle.ResolutionScoped,
93
token?: InjectionToken<T>
94
): ClassDecorator;
95
```
96
97
**Usage Examples:**
98
99
```typescript
100
// Container scoped - one instance per container
101
@scoped(Lifecycle.ContainerScoped)
102
@injectable()
103
class RequestContext {
104
constructor(private requestId: string) {}
105
}
106
107
// Resolution scoped - one instance per resolution chain
108
@scoped(Lifecycle.ResolutionScoped, "ICache")
109
@injectable()
110
class CacheService implements ICache {
111
private cache = new Map();
112
}
113
```
114
115
#### Auto-Injectable Decorator
116
117
Creates a parameterless constructor that automatically resolves dependencies, enabling use without manual container.resolve().
118
119
```typescript { .api }
120
/**
121
* Creates parameterless constructor with auto-resolved dependencies
122
* Enables instantiation without explicit container.resolve() call
123
* @returns Class decorator function
124
*/
125
function autoInjectable(): ClassDecorator;
126
```
127
128
**Usage Examples:**
129
130
```typescript
131
@autoInjectable()
132
@injectable()
133
class UserController {
134
constructor(private userService?: UserService) {}
135
136
getUsers() {
137
return this.userService?.getAllUsers() || [];
138
}
139
}
140
141
// Can be instantiated directly
142
const controller = new UserController(); // Dependencies auto-resolved
143
const users = controller.getUsers();
144
```
145
146
#### Registry Decorator
147
148
Registers multiple dependencies on a class, useful for configuring related services together.
149
150
```typescript { .api }
151
/**
152
* Registers multiple dependencies on class decoration
153
* @param registrations - Array of registration configurations
154
* @returns Class decorator function
155
*/
156
function registry(
157
registrations: ({
158
token: InjectionToken<any>;
159
options?: RegistrationOptions;
160
} & Provider<any>)[]
161
): ClassDecorator;
162
```
163
164
**Usage Examples:**
165
166
```typescript
167
@registry([
168
{ token: "ILogger", useClass: ConsoleLogger },
169
{ token: "IDatabase", useClass: SqlDatabase, options: { lifecycle: Lifecycle.Singleton } },
170
{ token: "ApiUrl", useValue: "https://api.example.com" }
171
])
172
@injectable()
173
class ServiceModule {
174
constructor() {
175
console.log("Service module initialized with dependencies");
176
}
177
}
178
```
179
180
### Parameter Decorators
181
182
Decorators applied to constructor parameters to specify injection behavior and dependency resolution.
183
184
#### Inject Decorator
185
186
Injects a single dependency for a constructor parameter using the specified token.
187
188
```typescript { .api }
189
/**
190
* Injects single dependency for constructor parameter
191
* @param token - Injection token to resolve
192
* @param options - Optional injection configuration
193
* @returns Parameter decorator function
194
*/
195
function inject(
196
token: InjectionToken<any>,
197
options?: { isOptional?: boolean }
198
): ParameterDecorator;
199
```
200
201
**Usage Examples:**
202
203
```typescript
204
@injectable()
205
class UserService {
206
constructor(
207
@inject("ILogger") private logger: ILogger,
208
@inject("DatabaseConfig") private config: DatabaseConfig,
209
@inject("Cache", { isOptional: true }) private cache?: ICache
210
) {}
211
}
212
213
// With symbols for type safety
214
const LOGGER_TOKEN = Symbol("ILogger");
215
216
@injectable()
217
class OrderService {
218
constructor(
219
@inject(LOGGER_TOKEN) private logger: ILogger
220
) {}
221
}
222
```
223
224
#### Inject All Decorator
225
226
Injects all registered dependencies for a token as an array, useful for plugin patterns.
227
228
```typescript { .api }
229
/**
230
* Injects all dependencies for token as array
231
* Perfect for plugin patterns and multiple providers
232
* @param token - Injection token to resolve all instances for
233
* @param options - Optional injection configuration
234
* @returns Parameter decorator function
235
*/
236
function injectAll(
237
token: InjectionToken<any>,
238
options?: { isOptional?: boolean }
239
): ParameterDecorator;
240
```
241
242
**Usage Examples:**
243
244
```typescript
245
@injectable()
246
class PluginManager {
247
constructor(
248
@injectAll("Plugin") private plugins: IPlugin[],
249
@injectAll("Validator", { isOptional: true }) private validators: IValidator[] = []
250
) {}
251
252
executePlugins() {
253
this.plugins.forEach(plugin => plugin.execute());
254
}
255
}
256
257
// Register multiple plugins
258
container.register("Plugin", EmailPlugin);
259
container.register("Plugin", SmsPlugin);
260
container.register("Plugin", PushPlugin);
261
```
262
263
#### Inject With Transform Decorator
264
265
Injects a dependency with transformation applied using a registered transformer function.
266
267
```typescript { .api }
268
/**
269
* Injects dependency with transformation applied
270
* @param token - Injection token to resolve
271
* @param transformer - Injection token for transform function
272
* @param args - Additional arguments passed to transformer
273
* @returns Parameter decorator function
274
*/
275
function injectWithTransform(
276
token: InjectionToken<any>,
277
transformer: InjectionToken<Transform<any, any>>,
278
...args: any[]
279
): ParameterDecorator;
280
```
281
282
**Usage Examples:**
283
284
```typescript
285
// Register transformer
286
container.register("StringToNumber", {
287
useValue: { transform: (value: string) => parseInt(value, 10) }
288
});
289
290
@injectable()
291
class MathService {
292
constructor(
293
@injectWithTransform("ConfigValue", "StringToNumber")
294
private maxItems: number
295
) {}
296
}
297
```
298
299
#### Inject All With Transform Decorator
300
301
Injects all dependencies for a token with transformation applied to the entire array.
302
303
```typescript { .api }
304
/**
305
* Injects all dependencies with transformation applied to array
306
* @param token - Injection token to resolve all instances for
307
* @param transformer - Injection token for transform function
308
* @param args - Additional arguments passed to transformer
309
* @returns Parameter decorator function
310
*/
311
function injectAllWithTransform(
312
token: InjectionToken<any>,
313
transformer: InjectionToken<Transform<[any], any>>,
314
...args: any[]
315
): ParameterDecorator;
316
```
317
318
**Usage Examples:**
319
320
```typescript
321
// Register array transformer
322
container.register("SortPlugins", {
323
useValue: {
324
transform: (plugins: IPlugin[]) => plugins.sort((a, b) => a.priority - b.priority)
325
}
326
});
327
328
@injectable()
329
class PluginOrchestrator {
330
constructor(
331
@injectAllWithTransform("Plugin", "SortPlugins")
332
private sortedPlugins: IPlugin[]
333
) {}
334
335
executeInOrder() {
336
this.sortedPlugins.forEach(plugin => plugin.execute());
337
}
338
}
339
```
340
341
## Types
342
343
```typescript { .api }
344
// Decorator function types
345
type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
346
type ParameterDecorator = (target: any, propertyKey: string | symbol, parameterIndex: number) => void;
347
348
// Injectable options
349
interface InjectableOptions<T> {
350
token?: InjectionToken<T> | InjectionToken<T>[];
351
}
352
353
// Injection options
354
interface InjectOptions {
355
isOptional?: boolean;
356
}
357
358
// Registry configuration
359
type RegistryConfiguration = ({
360
token: InjectionToken<any>;
361
options?: RegistrationOptions;
362
} & Provider<any>)[];
363
364
// Transform interface
365
interface Transform<TIn, TOut> {
366
transform(incoming: TIn, ...args: any[]): TOut;
367
}
368
```