@typesugar/derive
v0.1.0
Published
π§ Auto-derive common implementations (Eq, Ord, Clone, etc.) for typesugar
Maintainers
Readme
@typesugar/derive
Syntactic sugar for TypeScript with zero calories.
Overview
Typeclass operations work automatically on any type with derivable structure:
interface User {
id: number;
name: string;
email: string;
}
const alice: User = { id: 1, name: "Alice", email: "[email protected]" };
const bob: User = { id: 2, name: "Bob", email: "[email protected]" };
// Operators just work β auto-derived, auto-specialized
alice === bob; // false (compiles to: alice.id === bob.id && ...)
alice < bob; // true (lexicographic comparison)
// Methods just work too
alice.show(); // "User(id = 1, name = Alice, email = [email protected])"
alice.clone(); // deep copy
alice.toJson(); // JSON serializationNo decorators. No imports. The compiler derives typeclasses from type structure and inlines them to zero-cost code.
Installation
npm install @typesugar/derive
# or
pnpm add @typesugar/deriveImplicit Usage (Default)
Just use operators and methods on your types:
interface Point {
x: number;
y: number;
}
const p1: Point = { x: 1, y: 2 };
const p2: Point = { x: 1, y: 2 };
p1 === p2; // true β Eq typeclass
p1 < p2; // false β Ord typeclass
p1.show(); // "Point(x = 1, y = 2)" β Show typeclass
p1.clone(); // { x: 1, y: 2 } β Clone typeclass
p1.hash(); // 12345 β Hash typeclassEverything compiles to direct code:
// p1 === p2 compiles to:
p1.x === p2.x && p1.y === p2.y;Explicit Derivation (Optional)
Use @derive() to document capabilities in the type definition:
import { derive } from "@typesugar/derive";
@derive(Eq, Ord, Clone, Debug, Hash, Default, Json, Builder)
interface User {
id: number;
name: string;
email?: string;
}This is purely documentation β the same operations work without the decorator.
Available Typeclasses
Eq β Equality
interface Point {
x: number;
y: number;
}
p1 === p2; // true
p1.eq(p2); // true (method form)Ord β Ordering
interface Version {
major: number;
minor: number;
}
v1 < v2; // true (lexicographic by field order)
v1.compare(v2); // -1Show β String Representation
interface User {
id: number;
name: string;
}
user.show(); // "User(id = 1, name = Alice)"Clone β Deep Copy
interface Config {
settings: Map<string, string>;
}
const c2 = c1.clone(); // Deep copyHash β Hash Code
interface Point {
x: number;
y: number;
}
point.hash(); // Consistent number for hash mapsDefault β Default Value
interface Options {
enabled: boolean;
count: number;
}
Options.default(); // { enabled: false, count: 0 }Json β Serialization
interface User {
id: number;
name: string;
}
user.toJson(); // '{"id":1,"name":"Alice"}'
User.fromJson(json); // { id: 1, name: "Alice" }Builder β Fluent Builder
interface User {
id: number;
name: string;
email?: string;
}
new UserBuilder().withId(1).withName("Alice").build();TypeGuard β Runtime Type Check
interface User {
id: number;
name: string;
}
if (User.isUser(data)) {
console.log(data.name); // data is typed as User
}Custom Instances
When you need non-standard behavior:
import { instance } from "@typesugar/typeclass";
interface User {
id: number;
name: string;
passwordHash: string; // Should not affect equality
}
@instance
const userEq: Eq<User> = {
eq: (a, b) => a.id === b.id && a.name === b.name,
};API Reference
Types
DeriveTypeInfoβ Type information passed to derive macrosDeriveFieldInfoβ Field information withinDeriveTypeInfo
Functions
createDerivedFunctionName(operation, typeName)β Get the conventional function name for a derive operation
Derive Macros
EqDerive,OrdDerive,CloneDerive,DebugDeriveHashDerive,DefaultDerive,JsonDerive,BuilderDeriveTypeGuardDerive
License
MIT
