Traits
Traits define behavioral contracts that types can implement. They work with for blocks to ensure types provide specific functionality.
Defining a Trait
Section titled “Defining a Trait”A trait declares method signatures that implementing types must provide:
trait Display { fn display(self) -> string}Implementing a Trait
Section titled “Implementing a Trait”Use for Type: Trait to implement a trait for a type:
type User { name: string, age: number }
for User: Display { fn display(self) -> string { `${self.name} (${self.age})` }}The compiler checks that all required methods are implemented. Missing methods produce a clear error.
Default Implementations
Section titled “Default Implementations”Traits can provide default method bodies. Implementors inherit them unless they override:
trait Eq { fn eq(self, other: string) -> boolean fn neq(self, other: string) -> boolean { !(self |> eq(other)) }}
for User: Eq { fn eq(self, other: string) -> boolean { self.name == other } // neq is inherited from the default implementation}Multiple Traits
Section titled “Multiple Traits”A type can implement multiple traits:
for User: Display { fn display(self) -> string { self.name }}
for User: Eq { fn eq(self, other: string) -> boolean { self.name == other }}Deriving Traits
Section titled “Deriving Traits”Record types can auto-derive trait implementations with deriving. This generates the same code as a handwritten for block with no runtime cost:
type User { id: string, name: string, email: string,} deriving (Display)This generates display(self) -> string with a string representation like User(id: abc, name: Ryan, email: [email protected]).
Derivable traits
Section titled “Derivable traits”| Trait | Generated implementation |
|---|---|
Display | TypeName(field1: val1, field2: val2) format |
Deriving rules
Section titled “Deriving rules”derivingonly works on record types (not unions)- A handwritten
forblock overrides a derived implementation - Only
Displayis derivable —Eqis built-in via==
What It Compiles To
Section titled “What It Compiles To”Traits are erased at compile time. for User: Display compiles to exactly the same TypeScript as for User — the trait just tells the checker that a contract is satisfied.
// Floefor User: Display { fn display(self) -> string { self.name }}
// Compiled TypeScript (identical to plain for-block)function display(self: User): string { return self.name; }No class wrappers, no vtables, no runtime representation. Traits are purely a static checking tool.
- All required methods (those without default bodies) must be implemented
- Default methods are inherited unless overridden
- Traits are compile-time only — no runtime representation
- No orphan rules — scoping via imports handles conflicts
- No trait objects or dynamic dispatch — traits are a static checking tool