DeutschGitHub
prototypepackages/mixin-class-factory/src

Mixin Class Factory

@ralphschuler/mixin-class-factory

Composes instance fields and prototype methods with validated configuration defaults.

compositiondecoratorsconfig

01 · Problem

What is it for?

Copying instance fields does not copy class prototype methods or preserve private-field brands.

02 · Mental model

How should you think about it?

A mixin composition must define how configuration, fields and prototype descriptors combine.

In this repository

Composes instance fields and prototype methods with validated configuration defaults. Member collisions are rejected. Native private fields cannot be transplanted into another instance.

03 · Control flow

What happens in which order?

  1. Collect configuration requirements.
  2. Apply defaults and validate types.
  3. Construct each mixin.
  4. Copy permitted instance fields and prototype descriptors.
  5. Reject conflicting member names.

04 · Building blocks

The important contracts

ConfigProperty / InterfaceMethodDeclare configuration metadata and method contracts.
createClassCompose fields and prototype descriptors with collision checks.

05 · Build it yourself

Implement a small core

Start with this small independent implementation, then use the steps below to make its contract explicit.

  1. Collect configuration requirements.
  2. Apply defaults and validate types.
  3. Construct each mixin.
  4. Copy permitted instance fields and prototype descriptors.
  5. Reject conflicting member names.
Concept sketch · may reference omitted helpers
type Constructor<T = object> = new (...args: any[]) => T;

const WithLogging = <B extends Constructor>(Base: B) =>
  class extends Base {
    log(message: string) { console.log(message); }
  };

const WithId = <B extends Constructor>(Base: B) =>
  class extends Base { readonly id = crypto.randomUUID(); };

class Empty {}
class Service extends WithLogging(WithId(Empty)) {}

06 · Verify

What should you test?

  • Verify ordinary methods remain callable.
  • Test configuration defaults and type errors.
  • Reject conflicting names instead of silently overwriting behavior.

Try it yourself

Turn the first verification claim into a failing test, implement the smallest fix, then add a boundary case.

Verify ordinary methods remain callable.

Compare your approach

Your check should fail when the stated invariant is deliberately broken, and pass again after the fix. Keep setup deterministic and assert an observable result.

07 · Limits

Trade-offs and failure modes

  • Native private fields cannot be copied to unrelated instances.
  • Freezing is shallow.
  • Decorator metadata must not leak between subclasses.
Important

Member collisions are rejected. Native private fields cannot be transplanted into another instance.

08 · Keep exploring

Source code and related ideas

yarn tsx packages/mixin-class-factory/examples/basic.ts