簡體   English   中英

如何檢查 TypeScript 中產品類型的詳盡性?

[英]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);
};

這是它的工作原理。

  1. 如果props是空的 object,則空的 object 類型{}只能分配給typeof props
  2. 因此,當props為空 object 時, unhandled的類型為{} ,一切正常。
  3. 但是,當props不是空的 object 時, unhandled的類型never ,我們會收到編譯時錯誤。

因此,上述代碼將在解構時檢查產品類型的詳盡性。 如果將新屬性添加到Product類型,則props將不再可分配給unhandled ,並且我們將收到編譯時錯誤以表示不詳盡。

此外,您可以打開@typescript-eslint/no-unused-vars規則以確保使用所有解構屬性。 確保將ignoreRestSiblings選項設置為false

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM