The Type-System Mindset
type คือเซตของ value
หัวข้อที่มีชื่อว่า “type คือเซตของ value”นี่คือการปรับมุมมองที่ปลดล็อก TypeScript เลิกคิดว่า type เป็น ป้ายชื่อ แล้วเริ่มคิดว่าเป็น เซต — คือกลุ่มของ value ทุกตัวที่เป็นสมาชิกของตัวเองอย่างถูกต้อง
booleanคือเซต{ true, false }— มีสมาชิกสองตัวพอดีundefinedคือเซตที่มีสมาชิก หนึ่ง ตัว:{ undefined }stringคือเซต (อนันต์) ของ string ทั้งหมด42— ใช่ literal — คือเซตที่มีสมาชิก หนึ่ง ตัว:{ 42 }นี่คือ literal type
พอ type กลายเป็นเซต operation ที่คุณรู้จากคณิตศาสตร์อยู่แล้วก็อธิบายทั้ง system ได้
Assignability คือความสัมพันธ์แบบ subset
หัวข้อที่มีชื่อว่า “Assignability คือความสัมพันธ์แบบ subset”a assign ให้ b ได้ ก็ต่อเมื่อ เซต a เป็น subset ของเซต b นั่นคือกฎทั้งหมด
let x: 42 = 42;let y: number = x; // ✅ {42} ⊆ all numbers
let a: number = 42;let b: 42 = a; // ❌ all numbers ⊄ {42}// Error: Type 'number' is not assignable to type '42'.literal 42 พอดีเข้าไปใน number ได้เพราะ {42} เป็น subset ของทุกจำนวน ทางกลับกันพังเพราะจำนวนส่วนใหญ่ไม่ใช่ 42 คุณไม่ต้องท่องกฎ assignability เลย — แค่ถามว่า “เซตนี้อยู่ในเซตนั้นไหม”
union คือ set union; intersection คือ set intersection
หัวข้อที่มีชื่อว่า “union คือ set union; intersection คือ set intersection”flowchart TB
subgraph u["A หรือ B (union = OR)"]
ua["string"] --- ub["number"]
note1["value ที่อยู่ในเซตใดเซตหนึ่ง
ยิ่งมี value เยอะ ยิ่งกว้าง"]
end
subgraph i["A และ B (intersection = AND)"]
note2["value ที่อยู่ในทั้งสองเซต
ยิ่งมี value น้อย ยิ่งแคบ"]
end string | numberคือ union ของสองเซต — value ที่อยู่ใน เซตใดเซตหนึ่ง union จะ กว้างกว่า (สมาชิกเยอะกว่า)A & Bคือ intersection — value ที่อยู่ใน ทั้งสอง สำหรับ object type แปลว่า “มี property ของทั้งสองครบ” นั่นคือเหตุผลที่ intersection ทำให้ แคบลง
เรื่องน่าประหลาดใจที่พบบ่อยหลุดออกมาจากตรงนี้: string & number คือเซตว่าง ไม่มี value ไหนเป็นทั้ง string และ number — type ของตัวเองจึงเป็น never
สองปลายสุด: never และ unknown
หัวข้อที่มีชื่อว่า “สองปลายสุด: never และ unknown”เซตมีตัวเล็กสุดและใหญ่สุด และ TypeScript ตั้งชื่อให้:
neverคือ เซตว่าง{ }— ไม่มี value เลย ไม่มีอะไร assign ให้neverได้ (คุณสร้างสมาชิกของเซตว่างไม่ได้) แต่neverassign ให้ ทุกอย่าง ได้ (เซตว่างเป็น subset ของทุกเซต)neverคือ type ของ function ที่ไม่มีทาง return และเป็นสัญญาณว่า branch นั้นไปไม่ถึงunknownคือ เซตของ value ทั้งหมด — top type ทุกอย่าง assign ให้unknownได้ แต่unknownassign ให้แทบไม่มีอะไรได้จนกว่าคุณจะ narrow ก่อน พูดง่าย ๆunknownคือanyเวอร์ชันที่ปลอดภัยเรื่อง type
let n: never;let u: unknown = "anything goes";
let s: string = u; // ❌ unknown is too wide — narrow it firstlet x: unknown = 42; // ✅ everything fits into unknownany ทำลาย model นี้โดยตั้งใจ: เป็นการขอ ออก จากการเช็คเซตทั้งหมด นั่นคือเหตุผลที่อันตราย ส่วน unknown รักษา model ไว้และบังคับให้คุณ narrow