@orchestr-sh/traits · v0.1.0

Traits for TypeScript

PHP-style traits with decorators. Bring horizontal code reuse, conflict resolution, and composition to TypeScript.

$ npm install @orchestr-sh/traits reflect-metadata

Simple, elegant, powerful

Define traits with decorators. Apply them to any class.

traits-example.ts
import { Trait, UsesTraits } from '@orchestr-sh/traits';

@Trait()
class Timestampable {
  created_at?: Date;
  updated_at?: Date;

  touch(): void {
    this.updated_at = new Date();
  }
}

@Trait()
class SoftDeletes {
  deleted_at?: Date;

  softDelete(): void {
    this.deleted_at = new Date();
  }
}

@UsesTraits(Timestampable, SoftDeletes)
class User {
  name: string = '';

  // All trait methods are available
  touch!: () => void;
  softDelete!: () => void;
}

const user = new User();
user.touch();        // ✓ From Timestampable
user.softDelete();   // ✓ From SoftDeletes

Features

Everything you need for flexible code composition in TypeScript.

Multiple Traits

Apply as many traits as you need to a single class. No limit on horizontal code reuse.

Conflict Resolution

Handle method conflicts with @TraitInsteadOf and @TraitAlias decorators.

Trait Composition

Traits can use other traits. Build complex behaviors from simple, reusable pieces.

Type Safety

Full TypeScript support with autocomplete and compile-time type checking.

Runtime Inspection

Inspect traits at runtime with getTraits(), hasTrait(), and getTraitInfo().

Zero Dependencies

Lightweight package with only reflect-metadata as a peer dependency.

API at a glance

Four decorators and three helper functions. That's it.

@Trait()

Marks a class as a trait that can be used by other classes.

@UsesTraits(...traits)

Applies one or more traits to a class. Methods and properties are copied over.

@TraitAlias(trait, original, alias)

Creates an alias for a trait method to avoid naming conflicts.

@TraitInsteadOf(useTrait, method, ...insteadOf)

Resolves conflicts by specifying which trait's method to use.

getTraits(target)

Get all traits used by a class or instance.

hasTrait(target, trait)

Check if a class uses a specific trait.

getTraitInfo(target)

Get detailed trait metadata.

Elegant conflict resolution

When two traits define the same method, resolve it declaratively.

conflict-resolution.ts
import { Trait, UsesTraits, TraitInsteadOf, TraitAlias } from '@orchestr-sh/traits';

@Trait()
class TraitA {
  greet(): string { return 'Hello from A'; }
}

@Trait()
class TraitB {
  greet(): string { return 'Hello from B'; }
}

@UsesTraits(TraitA, TraitB)
@TraitInsteadOf(TraitA, 'greet', TraitB)  // Use TraitA's greet
@TraitAlias(TraitB, 'greet', 'greetB')    // Alias TraitB's greet
class MyClass {
  greet!: () => string;   // From TraitA
  greetB!: () => string;  // From TraitB (aliased)
}

Composition over inheritance

Start using PHP-style traits in your TypeScript projects today.