0
# Configuration
1
2
Global configuration settings for controlling mixin behavior. The `settings` object allows you to customize how ts-mixer handles prototype mixing, static properties, constructor initialization, and decorator inheritance.
3
4
## Capabilities
5
6
### Settings Object
7
8
Global configuration object that controls ts-mixer behavior across all mixin operations.
9
10
```typescript { .api }
11
/**
12
* Global settings object for configuring ts-mixer behavior
13
* Changes affect all subsequent mixin operations
14
*/
15
interface Settings {
16
/** Name of init function to call after construction, null to disable */
17
initFunction: string | null;
18
/** Strategy for handling static properties: 'copy' or 'proxy' */
19
staticsStrategy: "copy" | "proxy";
20
/** Strategy for mixing prototypes: 'copy' or 'proxy' */
21
prototypeStrategy: "copy" | "proxy";
22
/** Decorator inheritance strategy: 'deep', 'direct', or 'none' */
23
decoratorInheritance: "deep" | "direct" | "none";
24
}
25
26
/**
27
* Global settings instance - modify properties to change behavior
28
*/
29
declare const settings: Settings;
30
```
31
32
## Configuration Options
33
34
### Prototype Strategy
35
36
Controls how class prototypes are mixed together.
37
38
```typescript
39
import { settings } from "ts-mixer";
40
41
// Copy strategy (default) - better performance, ES5 compatible
42
settings.prototypeStrategy = "copy";
43
44
// Proxy strategy - dynamic updates, ES6+ only
45
settings.prototypeStrategy = "proxy";
46
```
47
48
**Copy Strategy (`"copy"`):**
49
- **Pros**: Better performance, ES5 compatible, no proxy overhead
50
- **Cons**: Static references - changes to base class prototypes after mixing aren't reflected
51
- **Use when**: Performance is critical, you don't modify prototypes after mixing
52
53
**Proxy Strategy (`"proxy"`):**
54
- **Pros**: Dynamic - updates to base classes are reflected in mixed classes
55
- **Cons**: Slower property access, requires ES6+ Proxy support
56
- **Use when**: You need dynamic prototype updates, prototype methods change at runtime
57
58
```typescript
59
import { Mixin, settings } from "ts-mixer";
60
61
class Base {
62
getValue(): string {
63
return "original";
64
}
65
}
66
67
class Other {
68
getOther(): string {
69
return "other";
70
}
71
}
72
73
// Test copy strategy
74
settings.prototypeStrategy = "copy";
75
class CopyMixed extends Mixin(Base, Other) {}
76
77
const copyInstance = new CopyMixed();
78
console.log(copyInstance.getValue()); // "original"
79
80
// Modify base class after mixing
81
Base.prototype.getValue = () => "modified";
82
83
console.log(copyInstance.getValue()); // Still "original" - not updated
84
85
// Test proxy strategy
86
settings.prototypeStrategy = "proxy";
87
class ProxyMixed extends Mixin(Base, Other) {}
88
89
const proxyInstance = new ProxyMixed();
90
console.log(proxyInstance.getValue()); // "modified" - dynamically updated
91
```
92
93
### Statics Strategy
94
95
Controls how static properties and methods are inherited.
96
97
```typescript
98
import { settings } from "ts-mixer";
99
100
// Copy strategy (default)
101
settings.staticsStrategy = "copy";
102
103
// Proxy strategy
104
settings.staticsStrategy = "proxy";
105
```
106
107
**Copy Strategy (`"copy"`):**
108
- Copies all static properties at mixin creation time
109
- Changes to base class statics after mixing aren't reflected
110
- Better performance for static property access
111
112
**Proxy Strategy (`"proxy"`):**
113
- Proxies static property access to base classes
114
- Dynamic updates to base class statics are reflected
115
- Slightly slower static property access
116
117
```typescript
118
import { Mixin, settings } from "ts-mixer";
119
120
class BaseClass {
121
static baseStaticProp: string = "base";
122
static baseStaticMethod(): string {
123
return "base method";
124
}
125
}
126
127
class OtherClass {
128
static otherStaticProp: string = "other";
129
}
130
131
// Test copy strategy
132
settings.staticsStrategy = "copy";
133
class CopyMixed extends Mixin(BaseClass, OtherClass) {}
134
135
console.log(CopyMixed.baseStaticProp); // "base"
136
console.log(CopyMixed.baseStaticMethod()); // "base method"
137
138
// Modify base class static after mixing
139
BaseClass.baseStaticProp = "modified base";
140
141
console.log(CopyMixed.baseStaticProp); // Still "base" - not updated
142
143
// Test proxy strategy
144
settings.staticsStrategy = "proxy";
145
class ProxyMixed extends Mixin(BaseClass, OtherClass) {}
146
147
console.log(ProxyMixed.baseStaticProp); // "modified base" - dynamically updated
148
```
149
150
### Init Function
151
152
Specifies a function name to call after construction with proper `this` context.
153
154
```typescript
155
import { settings } from "ts-mixer";
156
157
// Enable init function (disabled by default)
158
settings.initFunction = "init";
159
160
// Disable init function
161
settings.initFunction = null;
162
```
163
164
**Purpose:**
165
ES6 constructor limitations prevent ts-mixer from passing the correct `this` to constructors. The init function workaround allows constructor-like behavior with proper `this` context.
166
167
**Usage Pattern:**
168
169
```typescript
170
import { Mixin, settings } from "ts-mixer";
171
172
settings.initFunction = "init";
173
174
class Person {
175
public static allPeople: Set<Person> = new Set();
176
177
name: string;
178
179
constructor(name: string) {
180
this.name = name;
181
// Cannot use 'this' for side effects here in mixins
182
}
183
184
// Init function receives proper 'this' context
185
protected init(name: string) {
186
Person.allPeople.add(this); // This works correctly
187
}
188
}
189
190
class Employee {
191
public static allEmployees: Set<Employee> = new Set();
192
193
employeeId: number;
194
195
constructor(name: string, employeeId: number) {
196
this.employeeId = employeeId;
197
}
198
199
protected init(name: string, employeeId: number) {
200
Employee.allEmployees.add(this); // This works correctly
201
}
202
}
203
204
class PersonEmployee extends Mixin(Person, Employee) {}
205
206
// Both constructors and both init functions are called
207
const emp = new PersonEmployee("John Doe", 12345);
208
209
console.log(Person.allPeople.has(emp)); // true - init function worked
210
console.log(Employee.allEmployees.has(emp)); // true - init function worked
211
console.log(emp.name); // "John Doe" - constructor worked
212
console.log(emp.employeeId); // 12345 - constructor worked
213
```
214
215
**Init Function Features:**
216
- Called with the same arguments passed to the constructor
217
- Receives proper `this` context (unlike constructors in mixins)
218
- All init functions from mixed classes are called in order
219
- Optional - only classes that define the init function participate
220
221
### Decorator Inheritance
222
223
Controls how decorators are inherited during mixing.
224
225
```typescript
226
import { settings } from "ts-mixer";
227
228
// Deep inheritance (default) - inherit from all ancestors
229
settings.decoratorInheritance = "deep";
230
231
// Direct inheritance - only from direct mixin classes
232
settings.decoratorInheritance = "direct";
233
234
// No inheritance - disable decorator inheritance
235
settings.decoratorInheritance = "none";
236
```
237
238
**Deep Inheritance (`"deep"`):**
239
- Inherits decorators from all classes in the prototype chain
240
- Includes decorators from ancestor classes of mixed classes
241
- Most comprehensive decorator inheritance
242
243
**Direct Inheritance (`"direct"`):**
244
- Only inherits decorators from classes directly passed to `Mixin()`
245
- Ignores decorators from ancestor classes
246
- More predictable decorator behavior
247
248
**None (`"none"`):**
249
- Disables decorator inheritance completely
250
- Fastest option when decorators aren't needed
251
- Use for better performance when decorators aren't used
252
253
```typescript
254
import { Mixin, decorate, settings } from "ts-mixer";
255
256
function MyDecorator(name: string) {
257
return function(target: any) {
258
target.decoratorApplied = name;
259
};
260
}
261
262
@decorate(MyDecorator("grandparent"))
263
class GrandParent {}
264
265
@decorate(MyDecorator("parent"))
266
class Parent extends GrandParent {}
267
268
@decorate(MyDecorator("mixin"))
269
class MixinClass {}
270
271
// Deep inheritance
272
settings.decoratorInheritance = "deep";
273
class DeepMixed extends Mixin(Parent, MixinClass) {}
274
// Inherits decorators from: GrandParent, Parent, MixinClass
275
276
// Direct inheritance
277
settings.decoratorInheritance = "direct";
278
class DirectMixed extends Mixin(Parent, MixinClass) {}
279
// Inherits decorators from: Parent, MixinClass (not GrandParent)
280
281
// No inheritance
282
settings.decoratorInheritance = "none";
283
class NoDecorators extends Mixin(Parent, MixinClass) {}
284
// Inherits no decorators
285
```
286
287
## Configuration Examples
288
289
### Performance-Optimized Configuration
290
291
```typescript
292
import { settings } from "ts-mixer";
293
294
// Optimize for performance
295
settings.prototypeStrategy = "copy"; // Faster property access
296
settings.staticsStrategy = "copy"; // Faster static access
297
settings.decoratorInheritance = "none"; // Skip decorator processing
298
settings.initFunction = null; // Skip init function calls
299
300
// Use for high-performance scenarios where you don't need:
301
// - Dynamic prototype updates
302
// - Dynamic static updates
303
// - Decorator inheritance
304
// - Init function workarounds
305
```
306
307
### Dynamic Update Configuration
308
309
```typescript
310
import { settings } from "ts-mixer";
311
312
// Optimize for dynamic behavior
313
settings.prototypeStrategy = "proxy"; // Dynamic prototype updates
314
settings.staticsStrategy = "proxy"; // Dynamic static updates
315
settings.decoratorInheritance = "deep"; // Full decorator inheritance
316
settings.initFunction = "init"; // Enable init functions
317
318
// Use when you need:
319
// - Runtime modifications to base classes
320
// - Full decorator support
321
// - Constructor workarounds
322
```
323
324
### Balanced Configuration
325
326
```typescript
327
import { settings } from "ts-mixer";
328
329
// Balanced approach (default settings)
330
settings.prototypeStrategy = "copy"; // Good performance
331
settings.staticsStrategy = "copy"; // Good performance
332
settings.decoratorInheritance = "deep"; // Full decorator support
333
settings.initFunction = null; // Disabled by default
334
335
// Good for most use cases providing:
336
// - Reasonable performance
337
// - Full decorator inheritance
338
// - Simple constructor behavior
339
```
340
341
## Runtime Configuration Changes
342
343
Settings can be changed at runtime and affect all subsequent mixin operations:
344
345
```typescript
346
import { Mixin, settings } from "ts-mixer";
347
348
// Initial setting
349
settings.prototypeStrategy = "copy";
350
351
class A {}
352
class B {}
353
354
class Mixed1 extends Mixin(A, B) {} // Uses copy strategy
355
356
// Change setting
357
settings.prototypeStrategy = "proxy";
358
359
class Mixed2 extends Mixin(A, B) {} // Uses proxy strategy
360
361
// Mixed1 still uses copy, Mixed2 uses proxy
362
```
363
364
**Important Notes:**
365
- Settings changes don't affect already-created mixed classes
366
- Each mixin operation uses the current settings at the time of creation
367
- Consider setting configuration early in your application lifecycle