Traits
TypeScript interfaces are structural — Rust traits are nominal
Section titled “TypeScript interfaces are structural — Rust traits are nominal”In TypeScript, interfaces use structural typing: if an object has the right shape (the right properties and methods), it satisfies the interface — no explicit declaration needed.
Rust traits use nominal typing: a type only implements a trait if you explicitly write impl Trait for Type. Matching the shape is not enough. This distinction has important consequences for library design and correctness.
// TypeScript — structural typinginterface Greet { name(): string; hello(): string;}
// No explicit declaration — just match the shapeconst english = { name: () => "world", hello() { return `Hello, ${this.name()}!`; }};
function greetSomething(g: Greet) { console.log(g.hello());}
greetSomething(english); // works — english has the right shapetrait Greet { fn name(&self) -> &str; // Default method — free implementation, can be overridden fn hello(&self) -> String { format!("Hello, {}!", self.name()) }}
struct English;struct Thai;
impl Greet for English { fn name(&self) -> &str { "world" } // Uses the default hello()}
impl Greet for Thai { fn name(&self) -> &str { "โลก" } // Override the default fn hello(&self) -> String { format!("สวัสดี {}!", self.name()) }}
fn greet_something(g: &dyn Greet) { println!("{}", g.hello());}
fn main() { greet_something(&English); greet_something(&Thai);}Deriving common traits
Section titled “Deriving common traits”Rust can auto-generate implementations for many common traits using #[derive(...)]. TypeScript has no equivalent — you implement interfaces manually or use class inheritance.
// TypeScript — implement interfaces manually or use classesinterface Printable { toString(): string;}
class Point implements Printable { constructor(public x: number, public y: number) {} toString(): string { return `Point { x: ${this.x}, y: ${this.y} }`; } clone(): Point { return new Point(this.x, this.y); }}
const p = new Point(1, 2);console.log(p.toString());// Rust — derive common traits automatically#[derive(Debug, Clone, PartialEq)]struct Point { x: f64, y: f64,}
fn main() { let p1 = Point { x: 1.0, y: 2.0 }; let p2 = p1.clone(); // Clone derived println!("{:?}", p1); // Debug derived — prints: Point { x: 1.0, y: 2.0 } println!("equal: {}", p1 == p2); // PartialEq derived}Try it
Section titled “Try it”trait Greet { fn name(&self) -> &str; fn hello(&self) -> String { format!("Hello, {}!", self.name()) }}
struct English;struct Thai;
impl Greet for English { fn name(&self) -> &str { "world" }}
impl Greet for Thai { fn name(&self) -> &str { "โลก" } fn hello(&self) -> String { format!("สวัสดี {}!", self.name()) }}
fn main() { let e = English; let t = Thai; println!("{}", e.hello()); println!("{}", t.hello());}Compiling…