[英]Typescript: map union type to a single type
我試圖縮小(w/推斷)我想要從這個數組過濾器中取出的類型,但它給了我一個 TypeError: 'Item' is missing the following properties
type ItemList = (Item | ItemGroup )[];
type ItemGroup = {
name: string;
items: Item[];
}
type Item = {
key: string;
label: string;
}
const list: ItemList = [
{
key: 'key',
label: 'label'
},
{
name: 'name',
items: [
{
key: 'key1',
label: 'label2'
},
{
key: 'key3',
label: 'label4'
},
]
}
]
const groups: ItemGroup[] = list.filter( l => 'name' in l )
^^^^^^
// Type '(Item | ItemGroup)[]' is not assignable to type 'ItemGroup[]'.
// Type 'Item | ItemGroup' is not assignable to type 'ItemGroup'.
// Type 'Item' is missing the following properties from type 'ItemGroup': name, items ts(2322)
有任何想法嗎?
您有一個包含Item
和ItemGroup
元素的數組。 您希望將此數組過濾為僅包含ItemGroup
的元素,並且您希望打字稿了解您已過濾列表並知道返回的類型為ItemGroup[]
。
如何實現這一點是購買將l => 'name' in l
的過濾器轉換為它自己的類型保護函數。 返回類型value is ItemGroup
告訴打字稿“當且僅當這是真的,值的類型是 ItemGroup”。
const isItemGroup = (value: Item | ItemGroup): value is ItemGroup => 'name' in value;
const groups: ItemGroup[] = list.filter( isItemGroup );
通過使用類型保護,打字稿可以理解list.filter
的含義,你的錯誤就會消失。
不幸的是,編譯器不夠聰明,無法查看l => "name" in l
回調中的l => "name" in l
並理解它可用於縮小Item | ItemGroup
Item | ItemGroup
只是一個ItemGroup
。 幸運的是,您可以通過將其注釋為用戶定義的類型保護函數來告訴編譯器這是意圖:
const isItemGroup = (l: Item | ItemGroup): l is ItemGroup => "name" in l;
現在,如果您調用isItemGroup(l)
並且結果為true
,則編譯器將理解l
是一個ItemGroup
。 此外,標准庫為Array.prototype.filter()
提供了一個調用簽名,它接受用戶定義的類型保護回調並生成一個縮小的數組。 因此,通過使用isItemGroup
作為回調,您可以獲得所需的結果:
const groups: ItemGroup[] = list.filter(isItemGroup); // no error now
您可以使用類型 assertion 斷言過濾后的結果數組的類型為ItemGroup[]
:
const groups: ItemGroup[] = list.filter( l => 'name' in l ) as ItemGroup[]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.