Typescript 的 Utility Types 有很多,Partial 就是其中之一
Partial 的描述官方是這麼說的
Constructs a type with all properties of Type set to optional.
This utility will return a type that represents all subsets of a give type.
對岸碼農基本上直接翻譯再加上互相抄來抄去,描述都只有一種
Partial 可以快速把某个接口类型中定义的所有属性变成可选的。
其實不完全正確。因為 Partial 並非像上述所說直接把介面中的屬性變成可選,事實上它會複製一份 Type,並將屬性全部設置為可選的,也就是將所有屬性加上 ?
,所以它是產生了一個新的 Type,並非改變原始型別,舉個例子:
interface Student {
id: number
name: string
address: string
}
const Andy: Student = {
id: 1,
name: 'Andy'
}
先定義 Student 介面,接著宣告型別為 Student 的變數,因為未分配 address
的關係,我們得到以下錯誤
該錯誤表示 address 在 Student 型別中是必要的屬性,在不改變 Student 定義下,有兩種解決方法,一種是分配 address 毫無懸念,另一種是定義新的介面,將 address
設為可選的,像是這樣
interface NewStudent {
id: number
name: string
address?: string // 定義為可選的
}
// 沒有填寫 address 也不會報錯
const Andy: NewStudent = {
id: 1,
name: 'Andy'
}
嗯...好像有點奇怪,相似的介面為什麼要寫兩個?假若再添加一個新屬性 age,其情況與 address 相同,不就要反覆定義新的介面?而這些介面差異只在於屬性的可選性...
此時就是端出 Partial 的好時機,我們不需要定義新的介面,而是讓 Partial 去複製一份新的物件型別,其所有屬性就會變成可選。
改良上面的例子
interface Student {
id: number
name: string
address: string
}
const Andy: Partial<Student> = {
id: 1,
name: 'Andy'
}
如此一來,不定義 address 也不會報錯,就算不定義其他屬性也不會報錯,因為此時 Andy 的型別 Partial<Student>
會長這樣
{
id?: number
name?: string
address?: string
}
發現了嗎?所有 property 都是 optional!所以說 Partial 到底是如何實現的?來看原始碼
/**
* Make all properties in T optional
*/
type Partial<T> = {
[P in keyof T]?: T[P];
};
只有一句重點 [P in keyof T]? :T[P]
(關於 in
和 keyof
不再贅述)
解析
在 type 內部宣告一個變數 P,迭代型別 T 的每個 property,將每次遍歷結果分配給 P 以及設置 P 為 optional。
定義新的 type 為 Partial<Student>
interface Student {
id: number
name: string
address: string
age: number
}
type StudentInfo = Partial<Student>
檢查 StudentInfo
將 Student 型別分配給 Partial<T>
,它會返回一個新的型別 StudentInfo,其所有的 property 皆設置為可選的。
了解原理後,嘗試自行實作 Partial
type StudentPartial<T> = {
[P in keyof T]?: T[P]
}
const Andy: StudentPartial<Student> = {
id: 1,
name: 'Andy'
}
一一拆解後其實並不難,宛如一塊小蛋糕,適時地使用 Partial,讓程式碼更乾淨簡潔吧!
Thanks for reading the article 🌷 🌻 🌼
If you like it, please don't hesitate to click heart button ❤️
or follow my GitHub ⭐ I'd appreciate it.
Top comments (0)