ข้ามไปยังเนื้อหา

Enums and Match

TypeScript มี discriminated union: type union ที่สมาชิกแต่ละตัวมี field kind แบบ literal เพื่อ narrow type ส่วน enum ของ Rust เป็น first-class: แต่ละ variant เป็น type ที่มีชื่อซึ่งสามารถพก data ได้โดยตรง โดยไม่ต้องมี field kind ที่ทำเองด้วยมือ

ใน TypeScript คุณเขียน union ของ object type ส่วนใน Rust แต่ละ enum variant สามารถเก็บข้อมูลแบบ tuple, field ที่มีชื่อ หรือไม่เก็บอะไรเลยก็ได้:

// TypeScript discriminated union
type Shape =
| { kind: "circle"; radius: number }
| { kind: "rectangle"; width: number; height: number };
// Rust enum with data variants
enum Shape {
Circle(f64),
Rectangle(f64, f64),
}

เมื่อคุณ match บน enum ของ Rust compiler จะบังคับให้คุณจัดการทุก variant หากลืมไปแม้แต่ตัวเดียว build จะล้มเหลว

if let เป็นรูปแบบย่อของ match ที่มี arm ที่คุณสนใจเพียง arm เดียวและ fallback ที่คุณไม่สน:

if let Shape::Circle(r) = shape {
println!("radius is {r}");
}
TypeScript
type Shape =
| { kind: "circle"; radius: number }
| { kind: "rectangle"; width: number; height: number };
function area(shape: Shape): number {
switch (shape.kind) {
case "circle": return Math.PI * shape.radius ** 2;
case "rectangle": return shape.width * shape.height;
// TypeScript does not enforce exhaustiveness by default
}
}
Rust
enum Shape {
Circle(f64),
Rectangle(f64, f64),
}
fn area(shape: &Shape) -> f64 {
match shape {
Shape::Circle(r) => std::f64::consts::PI * r * r,
Shape::Rectangle(w, h) => w * h,
// forgetting a variant is a compile error
}
}
enum Shape {
Circle(f64),
Rectangle(f64, f64),
}
fn area(shape: &Shape) -> f64 {
match shape {
Shape::Circle(r) => std::f64::consts::PI * r * r,
Shape::Rectangle(w, h) => w * h,
}
}
fn main() {
let c = Shape::Circle(5.0);
let r = Shape::Rectangle(4.0, 6.0);
println!("Circle area: {:.2}", area(&c));
println!("Rectangle area: {:.2}", area(&r));
}
เกิดอะไรขึ้นถ้าคุณตกหล่น variant ใน `match` บน enum ของ Rust?
`if let` ใน Rust คืออะไร?
ไวยากรณ์ enum variant แบบใดของ Rust ที่พก field ที่มีชื่อ?