operator สองตัวนี้ช่วยให้คุณสร้าง type ขึ้นมาจาก type และค่าที่มีอยู่แล้ว ซึ่งเป็นพื้นฐานของการเขียนโปรแกรมในระดับ type
keyof — union ของ key ทั้งหมดในออบเจ็กต์ type
ts
interface User { id: number; name: string; }
type = keyof ;
const config = { host: "localhost", port: 3000 };
type Config = typeof config; // { host: string; port: number }
typeof (ในตำแหน่งของ type) จับ type ที่ infer ได้จากค่าตอน runtime ทำให้คุณไม่ต้องเขียน type ออกมาแยกต่างหาก
function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = { id: 1, name: "Ann" };
getProp(user, "name"); // returns string
getProp(user, "age"); // ❌ Error: "age" is not a key of user
ตรงนี้ K extends keyof T จำกัดให้ key เป็น key จริง ๆ เท่านั้น และ T[K] (ซึ่งเป็น indexed access type) จะคืน type ของค่าที่ตรงกับ key นั้นออกมาอย่างแม่นยำ การพิมพ์ผิดจะกลายเป็น compile error
const Roles = { Admin: "admin", User: "user" } as const;
type Role = typeof Roles[keyof typeof Roles]; // "admin" | "user"
keyof และ typeof เชื่อมโลกของค่ากับโลกของ type เข้าด้วยกัน
ทั้งสองตัวขับเคลื่อนการเข้าถึง property แบบ type-safe การสร้าง type จาก config/ค่าคงที่ (มีแหล่งความจริงเพียงแหล่งเดียว) และเป็นองค์ประกอบพื้นฐานสำหรับ mapped type และ conditional type
ทั้งสองตัวคือวิธีที่ช่วยให้คุณเลี่ยงการต้องดูแลนิยาม type ที่ขนานกันด้วยมือ