Add reusable behaviors to classes without deep inheritance chains
When to Use
Multiple unrelated classes need the same capability (e.g., serialization, event handling, logging)
Single inheritance is not sufficient to compose all required behaviors
You want to share behavior without creating a shared base class
Instructions
Define a mixin as a function that takes a superclass and returns a new class extending it.
Apply mixins by chaining: class MyClass extends Mixin2(Mixin1(Base)) {}.
Keep mixins focused on a single capability — avoid fat mixins that do too much.
Alternatively, use Object.assign(Target.prototype, mixinMethods) for simpler method injection.
// Functional mixin approach
const Serializable = (Base) =>
class extends Base {
serialize() {
return JSON.stringify(this);
}
static deserialize(json) {
return Object.assign(new this(), JSON.parse(json));
}
};
const Timestamped = (Base) =>
class extends Base {
constructor(...args) {
super(...args);
this.createdAt = new Date();
}
};
class User extends Serializable(Timestamped(class {})) {
constructor(name) {
super();
this.name = name;
}
}
const u = new User('Alice');
console.log(u.serialize()); // {"name":"Alice","createdAt":"..."}
Use TypeScript intersection types to type mixed-in methods correctly.
Details
JavaScript's single-prototype-chain inheritance means a class can only extend one parent. Mixins work around this by composing behaviors through function application rather than inheritance.
Trade-offs:
Method name collisions between mixins are silent — the last applied mixin wins
Stack traces can be confusing — intermediate mixin classes appear in the trace
instanceof checks do not work for mixins applied via Object.assign (only for the class mixin approach)
When NOT to use:
When composition via plain function calls or hooks would work just as well
When the behaviors are tightly coupled to specific base classes — inheritance is cleaner
For simple utility methods — just import a utility function
Read the instructions and examples in this document.
Apply the patterns to your implementation, adapting to your specific context.
Verify your implementation against the details and edge cases listed above.
Harness Integration
Type: knowledge — this skill is a reference document, not a procedural workflow.
No tools or state — consumed as context by other skills and agents.
Success Criteria
The patterns described in this document are applied correctly in the implementation.
Edge cases and anti-patterns listed in this document are avoided.
1---2name: js-mixin-pattern3description: JS Mixin Pattern4---5# JS Mixin Pattern67> Add reusable behaviors to classes without deep inheritance chains89## When to Use1011- Multiple unrelated classes need the same capability (e.g., serialization, event handling, logging)12- Single inheritance is not sufficient to compose all required behaviors13- You want to share behavior without creating a shared base class1415## Instructions16171. Define a mixin as a function that takes a superclass and returns a new class extending it.182. Apply mixins by chaining: `class MyClass extends Mixin2(Mixin1(Base)) {}`.193. Keep mixins focused on a single capability — avoid fat mixins that do too much.204. Alternatively, use `Object.assign(Target.prototype, mixinMethods)` for simpler method injection.2122```javascript23// Functional mixin approach24const Serializable = (Base) =>25 class extends Base {26 serialize() {27 return JSON.stringify(this);28 }29 static deserialize(json) {30 return Object.assign(new this(), JSON.parse(json));31 }32 };3334const Timestamped = (Base) =>35 class extends Base {36 constructor(...args) {37 super(...args);38 this.createdAt = new Date();39 }40 };4142class User extends Serializable(Timestamped(class {})) {43 constructor(name) {44 super();45 this.name = name;46 }47}4849const u = new User('Alice');50console.log(u.serialize()); // {"name":"Alice","createdAt":"..."}51```52535. Use TypeScript intersection types to type mixed-in methods correctly.5455## Details5657JavaScript's single-prototype-chain inheritance means a class can only extend one parent. Mixins work around this by composing behaviors through function application rather than inheritance.5859**Trade-offs:**6061- Method name collisions between mixins are silent — the last applied mixin wins62- Stack traces can be confusing — intermediate mixin classes appear in the trace63- `instanceof` checks do not work for mixins applied via `Object.assign` (only for the class mixin approach)6465**When NOT to use:**6667- When composition via plain function calls or hooks would work just as well68- When the behaviors are tightly coupled to specific base classes — inheritance is cleaner69- For simple utility methods — just import a utility function7071## Source7273https://patterns.dev/javascript/mixin-pattern7475## Process76771. Read the instructions and examples in this document.782. Apply the patterns to your implementation, adapting to your specific context.793. Verify your implementation against the details and edge cases listed above.8081## Harness Integration8283- **Type:** knowledge — this skill is a reference document, not a procedural workflow.84- **No tools or state** — consumed as context by other skills and agents.8586## Success Criteria8788- The patterns described in this document are applied correctly in the implementation.89- Edge cases and anti-patterns listed in this document are avoided.
Run npx skillmds@latest add intense-visions/js-mixin-pattern in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
JS Mixin Pattern It is listed under Coding & Dev Tools on SkillMD.
This skill has not completed SkillMD's automated safety review yet. Independent scanners report: SkillSpector: PASS, Skill Scanner: PASS. Capability flags: makes network calls. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
Intense-Visions (@intense-visions) published this skill. Their other Agent Skills are listed on their SkillMD profile.