Skip to main content

การจัดการกับ Object

บางครั้งเราต้องการเพิ่มคุณสมบัติใหม่ให้กับวัตถุ แต่การกระทำนี้อาจส่งผลให้เกิดข้อผิดพลาด ดูตัวอย่างด้านล่าง:

const nameRecord = {};
nameRecord.john = 1; // ❌ Error: Property 'john' does not exist on type '{}'.

เราไม่สามารถเพิ่มคุณสมบัติ 'john' ให้กับ nameRecord ได้เนื่องจากวัตถุไม่มีคุณสมบัตินั้น

ในการแก้ปัญหานี้ เราต้องใช้ Mapped Types ในกรณีนี้คือ Record

Record<Keys, Type>

Record ช่วยให้เราสามารถสร้างวัตถุที่สามารถเพิ่มคุณสมบัติใหม่ๆ ได้ ดูตัวอย่างด้านล่าง:

const nameRecord: Record<string, number> = {
john: 1,
micky: 2,
};

nameRecord['Lilly'] = 5; // เราสามารถเพิ่มคุณสมบัติใหม่ให้กับวัตถุได้ เพราะ 'Lilly' เป็นชนิดข้อมูล string

nameRecord[true] = 5; // ❌ ข้อผิดพลาด: ไม่สามารถใช้ชนิดข้อมูล 'true' เป็นคีย์

ในตัวอย่างนี้เราสร้างตัวแปร nameRecord ที่มีชนิดข้อมูล Record<string, number> ซึ่งอนุญาตให้เพิ่มคุณสมบัติที่มีชนิดข้อมูลเป็น string และค่าของคุณสมบัติเป็นชนิดข้อมูล number นอกจากนี้เรายังไม่สามารถใช้ค่าที่ไม่ใช่ string เป็นชนิดข้อมูลของคีย์ได้

Record with Type Union (จำเป็นต้องมีคีย์ครบทั้งหมด)

Record<Type> ต้องการให้กำหนดคีย์ของ Object ให้ครบถ้วน แต่ถ้าต้องการให้เป็นแบบ Partial (ไม่จำเป็นต้องมีคีย์ครบทั้งหมด) ตอนนี้ TypeScript ยังไม่ได้ support

type Activities = 'Running' | 'Walking' | 'Swimming';
const countActivities: Record<Activities, number> = {
Running: 0,
Swimming: 1,
Walking: 5
}

// คีย์ของ Object `countActivities` ต้องตรงกับชนิด `Activities`

ในตัวอย่างนี้ เรากำหนดชนิด Activities ที่ประกอบด้วยค่า 'Running', 'Walking', และ 'Swimming' แล้วเราสร้าง Object countActivities ที่มีชนิดข้อมูล Record<Activities, number> สิ่งนี้หมายความว่าวัตถุ countActivities ต้องมีคีย์ของคุณสมบัติตรงกับที่กำหนดในชนิด Activities ดังนั้นเราจึงต้องกำหนดค่าให้กับคุณสมบัติ 'Running', 'Walking', และ 'Swimming' ทั้งสามคุณสมบัติเสมอ

Record with Type Union (ไม่จำเป็นต้องมีคีย์ครบทั้งหมด)

ในกรณีที่ต้องการให้คุณสมบัติทั้งหมดเป็นตัวเลือก คุณสามารถใช้ Partial ร่วมกับ Record ดังตัวอย่าง:

type Activities = 'Running' | 'Walking' | 'Swimming';
const countActivities2: Partial<Record<Activities, number>> = {
Running: 0,
}

// คีย์ของ Object `countActivities2` ต้องตรงกับชนิด `Activities` และไม่จำเป็นต้องใส่ครบ

หรือคุณสามารถกำหนด PartialRecord<Type> เพื่อใช้งานเอง:

// กำหนด PartialRecord<Type> เพื่อใช้งานเอง
type PartialRecord<K extends keyof any, T> = Partial<Record<K, T>>

type Activities = 'Running' | 'Walking' | 'Swimming';
const countActivities: PartialRecord<Activities, number> = {
Running: 0,
}

countActivities.Walking = 5; // ใช้งานได้!
countActivities.Cycling = 4; // ❌ ข้อผิดพลาด: คุณสมบัติ 'Cycling' ไม่มีอยู่ในชนิด 'Partial<Record<Activities, number>>'

ในตัวอย่างนี้ เรากำหนดชนิด Activities ที่ประกอบด้วยค่า 'Running', 'Walking', และ 'Swimming' และสร้าง Object countActivities ที่มีชนิดข้อมูล PartialRecord<Activities, number> ซึ่งอนุญาตให้คุณสมบัติทั้งหมดใน Object เป็นตัวเลือก ไม่จำเป็นต้องใส่ครบทุกคีย์ แต่คีย์ที่ใช้ยังคงต้องอยู่ในชนิด Activities