在线不卡日本ⅴ一区v二区_精品一区二区中文字幕_天堂v在线视频_亚洲五月天婷婷中文网站

  • <menu id="lky3g"></menu>
  • <style id="lky3g"></style>
    <pre id="lky3g"><tt id="lky3g"></tt></pre>

    七爪源碼:自定義類型守衛(wèi)

    七爪源碼:自定義類型守衛(wèi)

    嘿,歡迎閱讀我們的 TypeScript Narrowing 系列的另一篇文章。 在這篇文章中,我將解釋:

  • 類型謂詞
  • 如何創(chuàng)建自己的警衛(wèi)
  • 如何通過排除創(chuàng)建守衛(wèi)
  • 這是我們系列的第三篇文章,如果你還沒有看過之前的文章,我強烈建議你去看看,它們?yōu)槭照峁┝藞詫嵉幕A。

    類型謂詞

    在上一篇文章中,我們探討了基本的類型保護運算符。 現(xiàn)在我想向你展示類型保護函數(shù)。

    例如,如果您需要檢查名為 value 的變量是否為字符串,則可以使用 typeof 運算符。 但你也可以做的是創(chuàng)建一個名為 isString() 的函數(shù),它接收一個參數(shù)并在給定參數(shù)是字符串時返回 true。

    const isString = (value: any): boolean => typeof value === ‘string’;

    還記得上一篇文章中的 formatErrorMessage() 函數(shù)嗎?

    const formatErrorMessage = ( value: null | undefined | string | Error | Warning): string => { const prefix = ‘Error: ‘; // If it’s falsy (null, undefined, empty string), return “Unknown” with the prefix if (!value) { return prefix + ‘Unknown’; } // If it’s a string, return the string with the prefix if (typeof value === ‘string’) { return prefix + value; } // If it’s a Warning, return the Warning.text with the prefix if (‘text’ in value) { return prefix + value.text; } // If it’s an Error, return the Error.message with the prefix if (value instanceof Error) { return prefix + value.message; } // We will never reach here throw new Error(`Invalid value type`);};interface Warning { text: string;}

    讓我們從中刪除 typeof 運算符并使用 isString() 代替。

    const formatErrorMessage = ( value: null | undefined | string | Error | Warning): string => { const prefix = ‘Error: ‘; // If it’s falsy (null, undefined, empty string), return “Unknown” with the prefix if (!value) { return prefix + ‘Unknown’; } // If it’s a string, return the string with the prefix if (isString(value)) { return prefix + value; } // If it’s a Warning, return the Warning.text with the prefix if (‘text’ in value) { return prefix + value.text; } // If it’s an Error, return the Error.message with the prefix if (value instanceof Error) { return prefix + value.message; } // We will never reach here throw new Error(`Invalid value type`);};interface Warning { text: string;}

    相同的代碼,我們只是在一個函數(shù)中隔離了守衛(wèi),對吧? 不,它壞了。 TypeScript 沒有將類型縮小為字符串,防護不起作用。

    事情是這樣的,isString() 返回一個布爾值,我們知道這個布爾值的含義。

    const isString = (value: any): boolean => typeof value === ‘string’;

    這意味著參數(shù)是一個字符串。 但是 TypeScript 不知道那個布爾值是什么意思,所以讓我們教它。

    與其說我們的函數(shù)返回一個布爾值,不如說我們的函數(shù)返回問題的答案:“這個參數(shù)是字符串嗎?”。

    鑒于我們的參數(shù)的名稱是 value,我們使用以下語法來做到這一點:value 是字符串。

    const isString = (value: any): value is string => typeof value === ‘string’;

    現(xiàn)在 TypeScript 知道 isString() 是一個類型保護并且我們的 formatErrorMessage() 函數(shù)可以正確編譯。

    我們的 isString() 函數(shù)的返回類型不再只是一個布爾值,它是一個“類型謂詞”。

    因此,要制作自定義類型保護,您只需定義一個返回類型謂詞的函數(shù)。

    所有類型謂詞都采用 { parameter } is { Type } 的形式。

    未知類型

    在我們繼續(xù)之前的快速提示:

    如果我們使用未知類型,我們的代碼會更安全,而不是在我們的自定義保護參數(shù)中使用類型 any。

    const isString = (value: unknown): value is string => typeof value === ‘string’;

    我制作了一個一分鐘的視頻來解釋任何和未知之間的區(qū)別,鏈接在參考資料中。

    自定義警衛(wèi)

    讓我們通過將 formatErrorMessage() 函數(shù)中的所有檢查轉換為自定義守衛(wèi)來鍛煉我們的知識。

    我們已經有了字符串保護,現(xiàn)在我們需要警告、錯誤虛假類型的保護。

    錯誤防護

    Error 的保護非常簡單,我們只是將 instanceof 操作符檢查隔離在一個函數(shù)中。

    const isError = (value: unknown): value is Error => value instanceof Error;

    警戒衛(wèi)士

    但另一方面,Warning 守衛(wèi)并不是那么簡單。

    TypeScript 允許我們使用 in 運算符,因為我們的 value 參數(shù)可以是有限數(shù)量的類型,并且它們都是對象。

    const formatErrorMessage = ( value: null | undefined | string | Error | Warning): string => { const prefix = ‘Error: ‘; // If it’s falsy (null, undefined, empty string), return “Unknown” with the prefix if (!value) { return prefix + ‘Unknown’; } // If it’s a string, return the string with the prefix if (isString(value)) { return prefix + value; } // If it’s a Warning, return the Warning.text with the prefix if (‘text’ in value) { return prefix + value.text; } // If it’s an Error, return the Error.message with the prefix if (isError(value)) { return prefix + value.message; } // We will never reach here throw new Error(`Invalid value type`);};interface Warning { text: string;}

    但是如果我們創(chuàng)建一個函數(shù)并說我們的參數(shù)是未知的,那么它可以是任何東西。 包括原始類型,這會引發(fā)錯誤,因為我們只能在對象中使用 in 運算符。

    interface Warning { text: string;}const isWarning = (value: unknown): value is Warning => ‘text’ in value; // Compilation error

    解決方案是在使用 in 運算符之前確保我們的參數(shù)是一個有效的對象。 我們還需要確保它不為空。

    interface Warning { text: string;}const isWarning = (value: unknown): value is Warning => typeof value === ‘object’ && value !== null && ‘text’ in value;

    假守衛(wèi)

    對于虛假值守衛(wèi),我們首先需要定義一個類型,其值被認為是虛假的。

    type Falsy = false | 0 | -0 | 0n | ” | null | undefined;

    我在這里不包括 NaN,因為 TypeScript 中沒有 NaN 類型。

    type Falsy = false | 0 | -0 | 0n | ” | null | undefined | ~~NaN~~;

    NaN 的類型是數(shù)字,并非所有數(shù)字都是假的,所以這就是我們不處理 NaN 的原因。

    typeof NaN;//=> number

    有一個提議將 NaN 添加為一種類型——以及整數(shù)、浮點數(shù)和無窮大。 我認為這很好,擁有這些類型會很有幫助。

    // Proposaltype number = integer | float | NaN | Infinity;

    我將在參考文獻中留下該提案的鏈接。

    無論如何,現(xiàn)在我們有了 Falsy 類型,我們可以創(chuàng)建一個 falsy 值守衛(wèi)。

    請記住,如果一個值在轉換為布爾值時被認為是假的,那么它就是假的。 因此,要檢查我們的值是否為假,我們可以使用抽象相等來查看它是否被轉換為假。

    type Falsy = false | 0 | -0 | 0n | ” | null | undefined;const isFalsy = (value: unknown): value is Falsy => value == false;

    帶有自定義警衛(wèi)的 formatErrorMessage()

    就是這樣,我們現(xiàn)在擁有了 formatErrorMessage() 函數(shù)所需的所有自定義守衛(wèi)。

    // FUNCTIONconst formatErrorMessage = ( value: null | undefined | string | Error | Warning): string => { const prefix = ‘Error: ‘; // If it’s falsy (null, undefined, empty string), return “Unknown” with the prefix if (isFalsy(value)) { return prefix + ‘Unknown’; } // If it’s a string, return the string with the prefix if (isString(value)) { return prefix + value; } // If it’s a Warning, return the Warning.text with the prefix if (isWarning(value)) { return prefix + value.text; } // If it’s an Error, return the Error.message with the prefix if (isError(value)) { return prefix + value.message; } // We will never reach here throw new Error(`Invalid value type`);};// GUARDSconst isString = (value: unknown): value is string => typeof value === ‘string’;const isError = (value: unknown): value is Error => value instanceof Error;interface Warning { text: string;}const isWarning = (value: unknown): value is Warning => typeof value === ‘object’ && value !== null && ‘text’ in value;type Falsy = false | 0 | -0 | 0n | ” | null | undefined;const isFalsy = (value: unknown): value is Falsy => value == false;

    獎勵:通過排除縮小范圍

    在我們結束之前,我想向你展示一些東西。

    虛假值的列表是有限的,對嗎?

    1. `false`2. `0` `-0` `0n` representations of zero3. ““ `””` `”` empty string4. `null`5. `undefined`6. `NaN` not a number

    但另一方面,真實值是無限的。 所有不虛假的價值觀都是真實的。

    那么,如何為真實值創(chuàng)建類型保護呢?

    誠實守衛(wèi)

    訣竅是排除虛假類型。

    我們不是檢查我們的值是否為真,而是檢查它是否_不_假。

    type Truthy = Exclude;const isTruthy = (value: T): value is Truthy => value == true;// Testconst x = ‘abc’ as null | string | 0;if (isTruthy(x)) { x.trim(); // `x: string`}

    我經常使用這個技巧,我們將在以后的文章中再次看到它。

    結論

    參考資料和其他鏈接如下。

    如果您還沒有,請在社交媒體上點贊、訂閱和關注我們。 這有助于我們成長,從而為您帶來更多免費內容。 這是雙贏的。

    鄭重聲明:本文內容及圖片均整理自互聯(lián)網,不代表本站立場,版權歸原作者所有,如有侵權請聯(lián)系管理員(admin#wlmqw.com)刪除。
    用戶投稿
    上一篇 2022年6月12日 14:46
    下一篇 2022年6月12日 14:46

    相關推薦

    聯(lián)系我們

    聯(lián)系郵箱:admin#wlmqw.com
    工作時間:周一至周五,10:30-18:30,節(jié)假日休息