Option, Result และ ไม่มี Null
TypeScript มี null, undefined, และ exception — Rust ไม่มีเลย
หัวข้อที่มีชื่อว่า “TypeScript มี null, undefined, และ exception — Rust ไม่มีเลย”TypeScript (และ JavaScript) มีสามวิธีในการแสดง “บางอย่างผิดพลาด”:
null— ความไม่มีของ value โดยตั้งใจundefined— value ที่ยังไม่ได้ initialize หรือหายไป- Exception ที่ throw — error ที่ escape call stack โดยไม่มองเห็น
ทั้งสามมองไม่เห็นใน function signature function ที่ return string อาจ return null อย่างเงียบๆ throw error หรือทำงานปกติ — คุณบอกไม่ได้จาก type
Rust ไม่มี null, ไม่มี undefined, และไม่มี exception Value ที่ไม่มีคือ Option<T> operation ที่ล้มเหลวได้ return Result<T, E> ทั้งคู่เป็นแค่ enum variant มองเห็นได้ใน function signature ทุกตัว
Option — type แบบ no-null
หัวข้อที่มีชื่อว่า “Option — type แบบ no-null”Option<T> เป็น enum ที่มีสอง variant: Some(T) (มี value) และ None (ไม่มี value) Compiler บังคับให้คุณ handle ทั้งคู่
// TypeScript — null อาจปรากฏอย่างเงียบๆfunction findUser(id: number): string | null { if (id === 1) return "Alice"; return null; // ลืมตรวจสอบได้ง่าย}
const user = findUser(2);console.log(user?.toUpperCase() ?? "not found");// ถ้าไม่มี optional chaining: user.toUpperCase() จะ throw TypeErrorfn find_user(id: u32) -> Option<String> { if id == 1 { Some("Alice".to_string()) } else { None }}
fn main() { // Pattern match — ต้อง handle ทั้งสอง case match find_user(2) { Some(name) => println!("found: {}", name), None => println!("not found"), }
// Helper ที่สะดวก let upper = find_user(1) .map(|s| s.to_uppercase()) .unwrap_or_else(|| "NOT FOUND".to_string()); println!("{}", upper);}Result — type แบบ no-exception
หัวข้อที่มีชื่อว่า “Result — type แบบ no-exception”Result<T, E> เป็น enum ที่มีสอง variant: Ok(T) (สำเร็จ) และ Err(E) (ล้มเหลว) Function ที่ล้มเหลวได้ return Result ทำให้ error มองเห็นใน type signature
// TypeScript — exception มองไม่เห็นใน signaturefunction parseNumber(s: string): number { const n = parseInt(s); if (isNaN(n)) throw new Error(`not a number: ${s}`); return n;}
try { const n = parseNumber("abc"); console.log(n * 2);} catch (e) { // ลืม try/catch ได้ง่าย — และ signature ไม่ได้บอกใบ้เลย console.error(e);}fn parse_and_double(s: &str) -> Result<i32, String> { let n: i32 = s.parse().map_err(|_| format!("not a number: {}", s))?; Ok(n * 2)}
fn main() { match parse_and_double("21") { Ok(v) => println!("doubled: {}", v), Err(e) => println!("error: {}", e), }
match parse_and_double("abc") { Ok(v) => println!("doubled: {}", v), Err(e) => println!("error: {}", e), }}ลองเขียนเอง
หัวข้อที่มีชื่อว่า “ลองเขียนเอง”fn parse_and_double(s: &str) -> Result<i32, String> { let n: i32 = s.parse().map_err(|_| format!("not a number: {}", s))?; Ok(n * 2)}
fn main() { match parse_and_double("21") { Ok(v) => println!("doubled: {}", v), Err(e) => println!("error: {}", e), }
let maybe: Option<i32> = Some(42); if let Some(v) = maybe { println!("got: {}", v); }
let none: Option<i32> = None; println!("unwrap_or: {}", none.unwrap_or(0));}Compiling…