TypeScript - กำหนดประเภทของคลาสและอาร์กิวเมนต์ของคอนสตรัคเตอร์โดยให้ซ้ำซ้อนน้อยที่สุด
ฉันมีคลาสแบบนี้อยู่ตอนนี้:
class Person {
id?: string = uuid();
name: string;
constructor(data: Person) {
_.merge(this, data);
}
}
โดยที่ 'uuid' เป็นฟังก์ชันที่สร้างรหัส และ '_' เป็น lodash
ปัญหาของฉันคือฉันมีฟังก์ชันที่ต้องการ id: function savePersonInDb(p: Person & { id: string }) {...} และ TypeScript จึงไม่ยอมให้เรียกใช้งานกับ new Person() เพราะว่า id เป็นค่าเลือก แต่จริง ๆ แล้วมันจะถูกสร้างขึ้นทุกครั้งเมื่อเรียก constructor
ฉันรู้ว่าฉันสามารถทำบางอย่างแบบ:
interface PersonData {
id?: string;
name: string;
}
class Person {
id: string = uuid();
name: string;
constructor(data: PersonData) {
_.merge(this, data);
}
}
แต่ฉันไม่ค่อยชอบความคิดที่จะต้องเขียนคุณสมบัติทั้งหมดสองครั้ง คุณเห็นทางไหนที่ฉันจะทำสิ่งที่ต้องการได้ง่ายกว่านี้ไหม?
โอ้ แล้วฉันลืมบอกไป แต่ในโปรเจกต์จริงของฉันฉันมีมากกว่า 2 แอตทริบิวต์ ดังนั้นฉันจะซาบซึ้งมากถ้าไม่ต้องเขียนมันซ้ำสองครั้งสำหรับทุกคลาส
ขอบคุณสำหรับความช่วยเหลือของคุณ!
คำตอบ #1
แล้วถ้าใช้ Omit เพื่อสร้างชนิดจาก Person ที่เอาการกำหนดชนิดทั้งหมดยกเว้น 'id' ซึ่งถูกทำให้เป็นทางเลือก (playground):
type OptionalId<T> = {
id?: string
} & Omit<T, 'id'>
// PersonData is automatically updated when Person is changed
type PersonData = OptionalId<Person>;
// savePersonInDb just takes Person
function savePersonInDb(person: Person) {}
class Person {
id: string = ''; // uuid();
name: string = '';
member1: number = 0;
// member2 and so on
constructor(data: PersonData) {
// _.merge(this, data);
}
}
// id is optional
const person = new Person({
name: 'test',
member1: 5
});
// new person object can be used.
savePersonInDb(person)
