在线不卡日本ⅴ一区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)
  • 這是我們系列的第三篇文章,如果你還沒有看過之前的文章,我強(qiáng)烈建議你去看看,它們?yōu)槭照峁┝藞?jiān)實(shí)的基礎(chǔ)。

    類型謂詞

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

    例如,如果您需要檢查名為 value 的變量是否為字符串,則可以使用 typeof 運(yùn)算符。 但你也可以做的是創(chuàng)建一個(gè)名為 isString() 的函數(shù),它接收一個(gè)參數(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 運(yùn)算符并使用 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;}

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

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

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

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

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

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

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

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

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

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

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

    未知類型

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

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

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

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

    自定義警衛(wèi)

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

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

    錯(cuò)誤防護(hù)

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

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

    警戒衛(wèi)士

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

    TypeScript 允許我們使用 in 運(yùn)算符,因?yàn)槲覀兊?value 參數(shù)可以是有限數(shù)量的類型,并且它們都是對(duì)象。

    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)建一個(gè)函數(shù)并說我們的參數(shù)是未知的,那么它可以是任何東西。 包括原始類型,這會(huì)引發(fā)錯(cuò)誤,因?yàn)槲覀冎荒茉趯?duì)象中使用 in 運(yùn)算符。

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

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

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

    假守衛(wèi)

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

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

    我在這里不包括 NaN,因?yàn)?TypeScript 中沒有 NaN 類型。

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

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

    typeof NaN;//=> number

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

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

    我將在參考文獻(xiàn)中留下該提案的鏈接。

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

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

    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;

    獎(jiǎng)勵(lì):通過排除縮小范圍

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

    虛假值的列表是有限的,對(duì)嗎?

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

    但另一方面,真實(shí)值是無限的。 所有不虛假的價(jià)值觀都是真實(shí)的。

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

    誠實(shí)守衛(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`}

    我經(jīng)常使用這個(gè)技巧,我們將在以后的文章中再次看到它。

    結(jié)論

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

    如果您還沒有,請?jiān)谏缃幻襟w上點(diǎn)贊、訂閱和關(guān)注我們。 這有助于我們成長,從而為您帶來更多免費(fèi)內(nèi)容。 這是雙贏的。

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

    相關(guān)推薦

    聯(lián)系我們

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