Skip to content

Utility Types ที่ควรรู้ใน TypeScript

Utility Types คือประเภทที่ TypeScript เตรียมไว้ให้สำหรับแปลงหรือจัดการกับชนิดข้อมูล (type) ให้สะดวกและปลอดภัยมากขึ้น เหมาะกับงานจริงในโปรเจกต์ยุคใหม่

Partial<T> (ทำให้เป็นบางส่วน)

แปลงทุก property ของ type ที่ระบุให้เป็น optional เหมาะกับกรณีที่ต้องการอัปเดตหรือแก้ไขบางส่วนของ object

ts
interface Todo {
  title: string;
  description: string;
}
function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
  // Partial<Todo> ทำให้ทุก property เป็น optional
  // สามารถส่งเฉพาะ property ที่ต้องการอัปเดตได้
  return { ...todo, ...fieldsToUpdate };
}

Required<T> (ทำให้จำเป็นต้องมี)

แปลงทุก property ของ type ที่ระบุให้เป็น required (บังคับต้องมีทุก property) ตรงข้ามกับ Partial

ts
interface Props {
  a?: number;
  b?: string;
}
const obj: Required<Props> = { a: 1, b: "hi" }; // ต้องมีทั้ง a และ b
// Required<Props> บังคับให้ต้องมีทุก property แม้จะประกาศเป็น optional ก็ตาม

Readonly<T> (ทำให้อ่านได้อย่างเดียว)

แปลงทุก property ของ type ที่ระบุให้เป็น readonly (ห้ามแก้ไขค่า)

ts
interface Todo {
  title: string;
}
const todo: Readonly<Todo> = { title: "Hello" };
// todo.title = "World"; // Error: read-only
// Readonly<Todo> ทำให้ไม่สามารถแก้ไขค่าหลังจากกำหนดค่าครั้งแรก

Record<K,T> (สร้างบันทึก)

สร้าง object type ที่ key เป็นชุดค่าที่กำหนด และ value เป็น type ที่กำหนด

ts
type CatName = "miffy" | "boris";
interface CatInfo { age: number; }
const cats: Record<CatName, CatInfo> = {
  miffy: { age: 10 },
  boris: { age: 5 }
};
// Record<K, T> สร้าง object ที่มี key เป็นประเภท K และ value เป็นประเภท T
// ในที่นี้ key ต้องเป็น "miffy" หรือ "boris" เท่านั้น และ value ต้องเป็น CatInfo

Pick<T,K> (เลือกเฉพาะ)

เลือกเฉพาะ property ที่ต้องการจาก type

ts
interface Todo {
  title: string;
  description: string;
  completed: boolean;
}
type TodoPreview = Pick<Todo, "title" | "completed">;
// Pick<Todo, "title" | "completed"> เลือกเฉพาะ property title และ completed จาก Todo
// ผลลัพธ์คือ type ที่มีแค่ { title: string; completed: boolean; }

Omit<T,K> (ละเว้น)

เหมือน Pick แต่เป็นการ "ตัดออก" ไม่เอา property ที่ระบุ

ts
interface Todo {
  title: string;
  description: string;
  completed: boolean;
}
type TodoPreview = Omit<Todo, "description">;
// Omit<Todo, "description"> ตัด property description ออกจาก Todo
// ผลลัพธ์คือ type ที่มี { title: string; completed: boolean; }

Exclude<T,U> (ไม่รวม)

ตัดค่าที่ตรงกับ type ที่ระบุออกจาก union type

ts
type T = Exclude<"a" | "b" | "c", "a">; // "b" | "c"
// Exclude<T, U> ตัดค่าที่เป็น U ออกจาก T
// ในที่นี้ตัด "a" ออกจาก "a" | "b" | "c" เหลือ "b" | "c"

Extract<T,U> (แยกออกมา)

เลือกเฉพาะค่าที่ตรงกับ type ที่ระบุจาก union type

ts
type T = Extract<"a" | "b" | "c", "a" | "f">; // "a"
// Extract<T, U> เลือกเฉพาะค่าที่เป็นทั้ง T และ U
// ในที่นี้ "a" เป็นค่าที่มีทั้งใน "a" | "b" | "c" และ "a" | "f"

NonNullable<T> (ไม่เป็นค่าว่าง)

ตัด null และ undefined ออกจาก type

ts
type T = NonNullable<string | number | undefined>; // string | number
// NonNullable<T> ตัด null และ undefined ออกจาก type T
// ในที่นี้ตัด undefined ออกจาก string | number | undefined

Parameters<T> (พารามิเตอร์)

ดึง parameter ของฟังก์ชัน type ออกมาเป็น tuple

ts
function f1(a: number, b: string): void {}
type Params = Parameters<typeof f1>; // [a: number, b: string]
// Parameters<T> ดึง type ของพารามิเตอร์จากฟังก์ชัน T ออกมาเป็น tuple
// ในที่นี้ดึงพารามิเตอร์ของ f1 ออกมาเป็น [number, string]

ReturnType<T> (ประเภทที่ส่งคืน)

ดึง return type ของฟังก์ชัน type

ts
function f1(): string { return "hi"; }
type R = ReturnType<typeof f1>; // string
// ReturnType<T> ดึง type ของค่าที่ return จากฟังก์ชัน T
// ในที่นี้ f1 return ค่าเป็น string จึงได้ type เป็น string

InstanceType<T> (ประเภทของอินสแตนซ์)

ดึง type ของ instance ที่ได้จาก constructor

ts
class C { x = 0; }
type T = InstanceType<typeof C>; // C
// InstanceType<T> ดึง type ของ instance ที่ได้จาก constructor T
// ในที่นี้ได้ type เป็น C ซึ่งเป็น type ของ instance ที่สร้างจาก class C