เข้าใจว่า homomorphic mapped type รักษา modifier ไว้อย่างไร และ clause as เปลี่ยนชื่อหรือกรอง key อย่างไร
เปิดบทเรียนนี้ใน KodokonMapped type วนซ้ำบนชุดของ key เพื่อผลิต object type ใหม่ รูปแบบ [K in keyof T] เรียกว่า homomorphic: คอมไพเลอร์รู้ว่าโครงสร้างมาจาก T และคัดลอก modifier readonly และ ? ของแต่ละ property เดิมมาโดยอัตโนมัติ คำนำหน้า + และ - ให้คุณเพิ่มหรือลบ modifier เหล่านี้ได้อย่างชัดเจน: นี่คือกลไกภายในที่อยู่เบื้องหลัง Partial, Required และ Readonly อย่างแท้จริง
type Mutable<T> = {
-readonly [K in keyof T]-?: T[K];
};
interface Config {
readonly host?: string;
readonly port?: number;
}
type Draft = Mutable<Config>;
// { host: string; port: number }ตั้งแต่ TypeScript 4.1 clause as เปิดใช้งาน key remapping: แต่ละ key สามารถถูกเปลี่ยนชื่อได้ทันที โดยทั่วไปผ่าน template literal type และหาก clause นั้นผลิต never key จะถูก ลบ ออกจากผลลัพธ์ไปเลย: นี่คือกลไกกรอง property อย่างเป็นทางการ สังเกต & string ในตัวอย่าง: keyof T อาจมี key ที่เป็น symbol หรือ number ซึ่งเข้ากันไม่ได้กับ template literal
type Getters<T> = {
[K in keyof T & string as `get${Capitalize<K>}`]:
() => T[K];
};
interface User { name: string; age: number }
type UserGetters = Getters<User>;
// { getName: () => string; getAge: () => number }
type OnlyMethods<T> = {
[K in keyof T as
T[K] extends (...args: never[]) => unknown
? K : never]: T[K];
};มีจุดละเอียดอ่อนในสเปกที่มักถูกมองข้าม: เมื่อนำไปใช้กับ array หรือ tuple, homomorphic mapped type จะ ไม่ ผลิต object ที่มี key 0, 1 และ length คอมไพเลอร์รักษาธรรมชาติของ type ไว้: มันแปลงสมาชิกและคงรูปทรงของ array หรือ tuple ไว้ นี่คือสิ่งที่ทำให้ Readonly<[number, string]> ยังคงเป็น tuple การรักษานี้จะหายไปทันทีที่ mapped type ไม่เป็น homomorphic อีกต่อไป เช่นกรณี [P in K] ที่ K เป็น union ของ key แบบใดก็ได้
type Immutable<T> = {
readonly [K in keyof T]: T[K];
};
type Pair = Immutable<[number, string]>;
// readonly [number, string]: the tuple survives
type List = Immutable<string[]>;
// readonly string[]as ผลิต never ให้กับ key หนึ่ง?{ readonly [K in keyof T]: T[K] } ผลิตอะไรเมื่อนำไปใช้กับ tuple [number, string]?-? ใน mapped type มีผลอย่างไร?