0.4.12 • Published 6 months ago

@rustable/trait v0.4.12

Weekly downloads
-
License
MIT
Repository
github
Last release
6 months ago

@rustable/trait

A TypeScript library that implements Rust-like traits with compile-time type checking and runtime verification.

✨ Features

  • 🔒 Type Safety - Type-safe trait definitions and implementations
  • 🎯 Generics - Support for generic traits and implementations
  • 🔄 Methods - Instance and static method implementations
  • 🔗 Composition - Trait-to-trait implementations
  • 💾 Memory - Memory-efficient using WeakMap for GC

📦 Installation

npm install @rustable/trait
# or
yarn add @rustable/trait
# or
pnpm add @rustable/trait

📖 Usage

Defining a Trait

import { Trait, macroTrait } from '@rustable/trait';

// Define a trait
class DisplayTrait extends Trait {
  display(): string {
    return 'default';
  }
}

// Create a trait decorator
const Display = macroTrait(DisplayTrait);

Implementing a Trait

There are several ways to implement a trait:

  1. Using the @derive decorator with default implementation:
@derive([Display])
class Point {
  constructor(
    public x: number,
    public y: number,
  ) {}
}

// The display method will use the default implementation from DisplayTrait
  1. Using implFor method with custom implementation:
class Point {
  constructor(
    public x: number,
    public y: number,
  ) {}
}

DisplayTrait.implFor(Point, {
  display() {
    return `(${this.x}, ${this.y})`;
  },
});

Using Traits

Once a trait is implemented, you can use it in several ways:

const point = new Point(1, 2);

// Method 1: Using wrap
const display = DisplayTrait.wrap(point);
console.log(display.display()); // "(1, 2)"

// Method 2: Checking implementation
if (DisplayTrait.isImplFor(point)) {
  const display = DisplayTrait.wrap(point);
  console.log(display.display());
}

Static Trait Methods

Traits can also include static methods:

class FromStrTrait extends Trait {
  static fromStr(s: string): any {
    throw new Error('Not implemented');
  }
}

const FromStr = macroTrait(FromStrTrait);

class Point {
  constructor(
    public x: number,
    public y: number,
  ) {}
}

// Implement static methods using implFor
FromStr.implFor(Point, {
  static: {
    fromStr(s: string): Point {
      const [x, y] = s.split(',').map(Number);
      return new Point(x, y);
    },
  },
});

// Use static trait methods
const point = FromStrTrait.staticWrap(Point).fromStr('1,2');

📚 API Reference

Core Functions

macroTrait

Creates a trait decorator for implementing traits at compile time.

const Display = macroTrait(DisplayTrait);
const FromStr = macroTrait(FromStrTrait);

@derive([Display, FromStr])
class Point {
  constructor(
    public x: number,
    public y: number,
  ) {}
}

// Implement custom behavior using implFor
DisplayTrait.implFor(Point, {
  display() {
    return `(${this.x}, ${this.y})`;
  },
});

FromStrTrait.implFor(Point, {
  static: {
    fromStr(s: string): Point {
      const [x, y] = s.split(',').map(Number);
      return new Point(x, y);
    },
  },
});

Trait Class Methods

The Trait class provides several static methods for trait operations:

isImplFor

Checks if a value implements the trait.

if (DisplayTrait.isImplFor(point)) {
  // point implements DisplayTrait
  const display = DisplayTrait.wrap(point);
  console.log(display.display());
}

validFor

Validates that a value implements the trait. Throws if validation fails.

// Throws if point doesn't implement DisplayTrait
DisplayTrait.validFor(point);

wrap

Wraps a value as a trait instance. Supports both instance and constructor wrapping.

// Wrap instance
const point = new Point(1, 2);
const display = DisplayTrait.wrap(point);
console.log(display.display());

// Wrap constructor
const PointDisplay = DisplayTrait.wrap(Point);
const newPoint = new PointDisplay(3, 4);

staticWrap

Wraps a class to access static trait methods.

// Wrap Point's static methods
const PointFromStr = FromStrTrait.staticWrap(Point);
const point = PointFromStr.fromStr('1,2');

implFor

Implements a trait for a target class.

DisplayTrait.implFor(Point, {
  display() {
    return `(${this.x}, ${this.y})`;
  },
});

tryImplFor

Similar to implFor, but doesn't throw if the trait is already implemented.

DisplayTrait.tryImplFor(Point, {
  display() {
    return `(${this.x}, ${this.y})`;
  },
});

📄 License

MIT © illuxiza

0.4.12

6 months ago

0.4.11

6 months ago

0.4.6

9 months ago

0.4.5

9 months ago

0.4.4

9 months ago

0.4.3

9 months ago

0.4.2

9 months ago

0.4.1

9 months ago

0.4.0

9 months ago

0.3.17

9 months ago

0.3.16

9 months ago

0.3.15

9 months ago

0.3.14

9 months ago

0.3.13

9 months ago

0.3.12

9 months ago

0.3.11

9 months ago

0.3.10

9 months ago

0.3.9

9 months ago

0.3.8

10 months ago

0.3.7

10 months ago

0.3.6

10 months ago

0.3.5

10 months ago

0.3.4

10 months ago

0.3.3

10 months ago

0.3.2

10 months ago

0.3.1

10 months ago

0.3.0

10 months ago

0.2.11

10 months ago

0.2.10

10 months ago

0.2.9

10 months ago

0.2.8

10 months ago

0.2.7

10 months ago

0.2.6

10 months ago

0.2.5

10 months ago

0.2.4

10 months ago

0.2.3

10 months ago

0.2.2

10 months ago

0.2.1

10 months ago

0.2.0

10 months ago

0.1.7

10 months ago

0.1.6

10 months ago

0.1.5

10 months ago

0.1.4

10 months ago

0.1.3

11 months ago

0.1.2

11 months ago

0.1.1

11 months ago

0.1.0

11 months ago

0.1.0-alpha.2

11 months ago

0.1.0-alpha.1

11 months ago

0.0.9

11 months ago