[英]How to check for exhaustiveness of product types in TypeScript?
很容易檢查 TypeScript 中總和類型的詳盡性。
type Sum =
| { tag: 'num'; value: number }
| { tag: 'str'; value: string };
const len = (sum: Sum): number => {
switch (sum.tag) {
case 'num': return sum.value;
case 'str': return sum.value.length;
default: {
const unhandled: never = sum;
throw new Error(`Unhandled sum ${unhandled}`);
}
}
};
現在,如果我向Sum
類型添加一個新變體,則sum
將不再可分配給unhandled
。 因此,我們會因為不詳盡而出現編譯時錯誤。
如何對 TypeScript 中的產品類型執行相同操作? 考慮以下示例。
type Product = {
num: number;
str: string;
};
const repeat = (product: Product): string => {
const { num, str } = product;
return str.repeat(num);
};
現在,如果我向Product
類型添加一個新屬性,那么我希望 TypeScript 編譯器報告非窮舉性錯誤,因為尚未對新屬性進行解構和使用。 我怎么做?
如果代碼因非詳盡而引發運行時錯誤,則加分。
讓我們從拋出一個運行時錯誤開始,因為它並不詳盡。 我們可以通過解構 rest 屬性來做到這一點,如果它有一個或多個可枚舉鍵則拋出錯誤。
const repeat = (product: Product): string => {
const { num, str, ...props } = product;
if (Object.keys(props).length > 0) {
throw new Error(`Unhandled props ${props}`);
}
return str.repeat(num);
};
接下來,為了讓 TypeScript 在編譯時檢查詳盡性,我們可以執行以下操作。
const repeat = (product: Product): string => {
const { num, str, ...props } = product;
const unhandled: {} extends typeof props ? {} : never = props;
if (Object.keys(unhandled).length > 0) {
throw new Error(`Unhandled props ${unhandled}`);
}
return str.repeat(num);
};
這是它的工作原理。
props
是空的 object,則空的 object 類型{}
只能分配給typeof props
。props
為空 object 時, unhandled
的類型為{}
,一切正常。props
不是空的 object 時, unhandled
的類型never
,我們會收到編譯時錯誤。 因此,上述代碼將在解構時檢查產品類型的詳盡性。 如果將新屬性添加到Product
類型,則props
將不再可分配給unhandled
,並且我們將收到編譯時錯誤以表示不詳盡。
此外,您可以打開@typescript-eslint/no-unused-vars
規則以確保使用所有解構屬性。 確保將ignoreRestSiblings
選項設置為false
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.