or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdcore-mixing.mddecorators.mdgeneric-classes.mdindex.mdmixin-detection.md

core-mixing.mddocs/

0

# Core Mixing

1

2

Core mixin functionality for creating classes that inherit from multiple base classes. The Mixin function is the primary way to combine multiple classes into a single class.

3

4

## Capabilities

5

6

### Mixin Function

7

8

Creates a new class that inherits properties and methods from multiple base classes.

9

10

```typescript { .api }

11

/**

12

* Creates a new class by mixing multiple classes together

13

* Supports up to 10 classes with full type inference

14

*/

15

function Mixin<A extends any[], I1, S1>(

16

c1: Class<A, I1, S1>

17

): Class<A, I1, S1>;

18

19

function Mixin<

20

A1 extends any[], I1, S1,

21

A2 extends any[], I2, S2

22

>(

23

c1: Class<A1, I1, S1>,

24

c2: Class<A2, I2, S2>

25

): Class<Longest<A1, A2>, I1 & I2, S1 & S2>;

26

27

function Mixin<

28

A1 extends any[], I1, S1,

29

A2 extends any[], I2, S2,

30

A3 extends any[], I3, S3

31

>(

32

c1: Class<A1, I1, S1>,

33

c2: Class<A2, I2, S2>,

34

c3: Class<A3, I3, S3>

35

): Class<Longest<A1, A2, A3>, I1 & I2 & I3, S1 & S2 & S3>;

36

37

function Mixin<

38

A1 extends any[], I1, S1,

39

A2 extends any[], I2, S2,

40

A3 extends any[], I3, S3,

41

A4 extends any[], I4, S4

42

>(

43

c1: Class<A1, I1, S1>,

44

c2: Class<A2, I2, S2>,

45

c3: Class<A3, I3, S3>,

46

c4: Class<A4, I4, S4>

47

): Class<Longest<A1, A2, A3, A4>, I1 & I2 & I3 & I4, S1 & S2 & S3 & S4>;

48

49

function Mixin<

50

A1 extends any[], I1, S1,

51

A2 extends any[], I2, S2,

52

A3 extends any[], I3, S3,

53

A4 extends any[], I4, S4,

54

A5 extends any[], I5, S5

55

>(

56

c1: Class<A1, I1, S1>,

57

c2: Class<A2, I2, S2>,

58

c3: Class<A3, I3, S3>,

59

c4: Class<A4, I4, S4>,

60

c5: Class<A5, I5, S5>

61

): Class<Longest<A1, A2, A3, A4, A5>, I1 & I2 & I3 & I4 & I5, S1 & S2 & S3 & S4 & S5>;

62

63

function Mixin<

64

A1 extends any[], I1, S1,

65

A2 extends any[], I2, S2,

66

A3 extends any[], I3, S3,

67

A4 extends any[], I4, S4,

68

A5 extends any[], I5, S5,

69

A6 extends any[], I6, S6

70

>(

71

c1: Class<A1, I1, S1>,

72

c2: Class<A2, I2, S2>,

73

c3: Class<A3, I3, S3>,

74

c4: Class<A4, I4, S4>,

75

c5: Class<A5, I5, S5>,

76

c6: Class<A6, I6, S6>

77

): Class<Longest<A1, A2, A3, A4, A5, A6>, I1 & I2 & I3 & I4 & I5 & I6, S1 & S2 & S3 & S4 & S5 & S6>;

78

79

function Mixin<

80

A1 extends any[], I1, S1,

81

A2 extends any[], I2, S2,

82

A3 extends any[], I3, S3,

83

A4 extends any[], I4, S4,

84

A5 extends any[], I5, S5,

85

A6 extends any[], I6, S6,

86

A7 extends any[], I7, S7

87

>(

88

c1: Class<A1, I1, S1>,

89

c2: Class<A2, I2, S2>,

90

c3: Class<A3, I3, S3>,

91

c4: Class<A4, I4, S4>,

92

c5: Class<A5, I5, S5>,

93

c6: Class<A6, I6, S6>,

94

c7: Class<A7, I7, S7>

95

): Class<Longest<A1, A2, A3, A4, A5, A6, A7>, I1 & I2 & I3 & I4 & I5 & I6 & I7, S1 & S2 & S3 & S4 & S5 & S6 & S7>;

96

97

function Mixin<

98

A1 extends any[], I1, S1,

99

A2 extends any[], I2, S2,

100

A3 extends any[], I3, S3,

101

A4 extends any[], I4, S4,

102

A5 extends any[], I5, S5,

103

A6 extends any[], I6, S6,

104

A7 extends any[], I7, S7,

105

A8 extends any[], I8, S8

106

>(

107

c1: Class<A1, I1, S1>,

108

c2: Class<A2, I2, S2>,

109

c3: Class<A3, I3, S3>,

110

c4: Class<A4, I4, S4>,

111

c5: Class<A5, I5, S5>,

112

c6: Class<A6, I6, S6>,

113

c7: Class<A7, I7, S7>,

114

c8: Class<A8, I8, S8>

115

): Class<Longest<A1, A2, A3, A4, A5, A6, A7, A8>, I1 & I2 & I3 & I4 & I5 & I6 & I7 & I8, S1 & S2 & S3 & S4 & S5 & S6 & S7 & S8>;

116

117

function Mixin<

118

A1 extends any[], I1, S1,

119

A2 extends any[], I2, S2,

120

A3 extends any[], I3, S3,

121

A4 extends any[], I4, S4,

122

A5 extends any[], I5, S5,

123

A6 extends any[], I6, S6,

124

A7 extends any[], I7, S7,

125

A8 extends any[], I8, S8,

126

A9 extends any[], I9, S9

127

>(

128

c1: Class<A1, I1, S1>,

129

c2: Class<A2, I2, S2>,

130

c3: Class<A3, I3, S3>,

131

c4: Class<A4, I4, S4>,

132

c5: Class<A5, I5, S5>,

133

c6: Class<A6, I6, S6>,

134

c7: Class<A7, I7, S7>,

135

c8: Class<A8, I8, S8>,

136

c9: Class<A9, I9, S9>

137

): Class<Longest<A1, A2, A3, A4, A5, A6, A7, A8, A9>, I1 & I2 & I3 & I4 & I5 & I6 & I7 & I8 & I9, S1 & S2 & S3 & S4 & S5 & S6 & S7 & S8 & S9>;

138

139

function Mixin<

140

A1 extends any[], I1, S1,

141

A2 extends any[], I2, S2,

142

A3 extends any[], I3, S3,

143

A4 extends any[], I4, S4,

144

A5 extends any[], I5, S5,

145

A6 extends any[], I6, S6,

146

A7 extends any[], I7, S7,

147

A8 extends any[], I8, S8,

148

A9 extends any[], I9, S9,

149

A10 extends any[], I10, S10

150

>(

151

c1: Class<A1, I1, S1>,

152

c2: Class<A2, I2, S2>,

153

c3: Class<A3, I3, S3>,

154

c4: Class<A4, I4, S4>,

155

c5: Class<A5, I5, S5>,

156

c6: Class<A6, I6, S6>,

157

c7: Class<A7, I7, S7>,

158

c8: Class<A8, I8, S8>,

159

c9: Class<A9, I9, S9>,

160

c10: Class<A10, I10, S10>

161

): Class<Longest<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>, I1 & I2 & I3 & I4 & I5 & I6 & I7 & I8 & I9 & I10, S1 & S2 & S3 & S4 & S5 & S6 & S7 & S8 & S9 & S10>;

162

```

163

164

**Usage Examples:**

165

166

```typescript

167

import { Mixin } from "ts-mixer";

168

169

// Basic mixin with two classes

170

class Disposable {

171

isDisposed: boolean = false;

172

dispose() {

173

this.isDisposed = true;

174

}

175

}

176

177

class Activatable {

178

isActive: boolean = false;

179

activate() {

180

this.isActive = true;

181

}

182

deactivate() {

183

this.isActive = false;

184

}

185

}

186

187

class SmartObject extends Mixin(Disposable, Activatable) {

188

interact() {

189

this.activate();

190

console.log("Interacting with active object");

191

}

192

}

193

194

const obj = new SmartObject();

195

obj.activate();

196

obj.dispose();

197

console.log(obj.isActive, obj.isDisposed); // true, true

198

199

// Mixing classes that extend other classes

200

class Animal {

201

name: string;

202

constructor(name: string) {

203

this.name = name;

204

}

205

}

206

207

class Mammal extends Animal {

208

warmBlooded: boolean = true;

209

}

210

211

class Flyable {

212

fly() {

213

return "Flying!";

214

}

215

}

216

217

class Bat extends Mixin(Mammal, Flyable) {

218

constructor(name: string) {

219

super(name);

220

}

221

222

hunt() {

223

return `${this.name} is ${this.fly().toLowerCase()} and hunting`;

224

}

225

}

226

227

const bat = new Bat("Vampire Bat");

228

console.log(bat.hunt()); // "Vampire Bat is flying! and hunting"

229

console.log(bat.warmBlooded); // true

230

231

// Mixing abstract classes (requires TypeScript 4.2+)

232

abstract class Shape {

233

abstract getArea(): number;

234

}

235

236

abstract class Named {

237

abstract getName(): string;

238

}

239

240

class Circle extends Mixin(Shape, Named) {

241

constructor(private radius: number, private name: string) {

242

super();

243

}

244

245

getArea(): number {

246

return Math.PI * this.radius * this.radius;

247

}

248

249

getName(): string {

250

return this.name;

251

}

252

}

253

254

const circle = new Circle(5, "My Circle");

255

console.log(`${circle.getName()}: ${circle.getArea()}`);

256

```

257

258

## Mixin Behavior

259

260

### Constructor Handling

261

262

When mixing classes, ts-mixer creates instances of each base class and copies their properties to the mixed instance. This means:

263

264

- Each base class constructor is called with the same arguments

265

- Constructor side effects involving `this` may not work as expected

266

- Use init functions (configured via `settings.initFunction`) for `this`-dependent side effects

267

268

### Property Copying

269

270

- Instance properties from all base classes are copied to the mixed instance

271

- Static properties are handled according to `settings.staticsStrategy`

272

- Getters and setters are properly preserved

273

- Protected and private properties are supported

274

275

### Method Resolution

276

277

- When multiple classes define the same method, the last class in the mixin list takes precedence

278

- Method resolution follows the prototype chain of the mixed class

279

- Override precedence can be controlled by the order of classes in the mixin call

280

281

### Static Property Inheritance

282

283

Static properties and methods from all base classes are inherited by the mixed class, subject to the configured strategy:

284

285

- `'copy'` strategy: Static properties are copied at mixin creation time

286

- `'proxy'` strategy: Static property access is proxied to base classes

287

288

## Error Handling

289

290

The Mixin function will throw errors in the following scenarios:

291

292

- Invalid arguments (non-constructor functions)

293

- Circular mixin dependencies

294

- Memory-related issues with very deep prototype chains

295

296

When using proxy strategies, additional errors may be thrown:

297

- Cannot set prototype of proxies created by ts-mixer

298

- Cannot define new properties on proxies created by ts-mixer

299

- Cannot delete properties on proxies created by ts-mixer