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

Objects, Arrays & Tuples

object type อธิบาย shape ด้วยการ list property modifier สองตัวสื่อความหมายเยอะ:

interface User {
readonly id: string; // reassign ไม่ได้หลังสร้าง
name: string; // required
email?: string; // optional — string | undefined
}
  • readonly บล็อกการ reassign property เป็น compile-time เท่านั้น (runtime ไม่ได้กันการ mutate) แต่สื่อและ enforce เจตนา
  • ? (optional) หมายถึง property อาจไม่มี สำคัญคือ optional property มี type T | undefined คุณจึงต้อง handle case undefined:
function greet(u: User) {
u.email.toLowerCase();
// ❌ Object is possibly 'undefined'.
u.email?.toLowerCase(); // ✅ optional chaining จัดการกรณีไม่มี
}

interface กับ type แทบใช้แทนกันได้สำหรับ object shape; interface เปิดต่อได้ (declaration merging) และ idiomatic สำหรับ public object contract ส่วน type ยังเขียน union, tuple และ mapped type ได้ ใช้ type เมื่อต้องการพวกนั้น สำหรับ object ธรรมดาใช้อันไหนก็ได้

เมื่อยังไม่รู้ key ล่วงหน้า index signature type ทุก key แบบ uniform:

interface Scores {
[player: string]: number;
}
const s: Scores = { ada: 10, alan: 12 };
s.grace = 9; // ✅ key เป็น string ใด ๆ, value เป็น number

ราคาที่ต้องจ่ายคือความซื่อสัตย์เรื่องการไม่มีค่า: s.someone มี type number แต่จริง ๆ เป็น undefined ตอน runtime ด้วย option noUncheckedIndexedAccess TypeScript จะทำให้เรื่องนี้เป็นจริง โดย type ทุก index access เป็น number | undefined — เป็น setting ที่แนะนำอย่างยิ่ง

array คือ list ที่ homogeneous และยาวเท่าไรก็ได้: number[] คือ “number กี่ตัวก็ได้” tuple คือ list ความยาวคงที่ที่แต่ละตำแหน่งมี type ของตัวเอง:

let list: number[] = [1, 2, 3, 4]; // ยาวเท่าไรก็ได้ เป็น number หมด
let point: [number, number] = [10, 20]; // number สองตัวพอดี
let pair: [string, number] = ["age", 36]; // ตำแหน่ง 0 string, ตำแหน่ง 1 number

tuple ขับเคลื่อน pattern อย่าง return ของ useState ใน React ([value, setter]) และพิกัดแบบมีชื่อกลาย ๆ tuple ยังรองรับ label (เป็น documentation ไม่มีผล runtime) และ rest element:

type HttpResult = [status: number, body: string];
type Args = [first: string, ...rest: number[]];
flowchart TB
  arr["number[]
any length · all same type"] --> arrEx["[1, 2, 3, 4, ...]"]
  tup["[string, number]
fixed length · per-position type"] --> tupEx["['age', 36]"]
array homogeneous และยืดหยุ่น; tuple positional และคงที่

readonly number[] (หรือ ReadonlyArray<number>) ห้าม method ที่ mutate อย่าง push และการ assign ที่ index — เหมาะกับ parameter ที่คุณสัญญาว่าจะไม่แก้ และจำจากบทที่แล้ว: as const บน array literal ให้ readonly tuple ของ literal พอดี:

const rgb = [255, 128, 0] as const;
// type: readonly [255, 128, 0]
function paint(color: readonly number[]) { /* mutate color ไม่ได้ */ }

การเลือกใช้ readonly array parameter เป็นนิสัยราคาถูกที่ได้ค่ามาก: กันบั๊ก mutate โดยไม่ตั้งใจทั้งชุด และสื่อเรื่อง ownership

type ของ optional property `email?: string` คืออะไร?
option `noUncheckedIndexedAccess` เปลี่ยนอะไร?
ความต่างระหว่าง `number[]` กับ `[number, number]` คืออะไร?
`[255, 128, 0] as const` ให้ type อะไร?