TypeScript 3.7 發布,帶來 Optional Chaining 等特性

←手機掃碼閱讀     admin @ 2019-11-11 , reply:0

TypeScript 3.7 發布了,此版本帶來了許多新特性。

Optional Chaining

首先一大亮點是 Optional Chaining,這是社區呼喚特彆強烈的一個 ECMAScript 特性。最初它是 TypeScript 的 issue 跟蹤器上第 16 個 issue,於 5 年前提交,要知道目前總共有多達 23000 個 issue。當時 TC39 還沒有正式提案,這些年來開發者一直要求實現該特性,但是為了不與 ECMAScript 建議衝突,遲遲沒有實現,相反 TS 開發團隊一直在幫助推動該提案實現標準化,並最終推及所有 JavaScript 與 TypeScript 開發者。 

Optional Chaining 特性主要用於保護出現在屬性路徑中 null 和 undefined 值,像 C# 等語言中已經有用於訪問屬性鏈的語法糖,可以在對象層次結構中的任何地方處理遇到的 null 和 undefined 情況,使它可以正常執行,而不會拋出錯誤。

具體來講,在向樹狀結構深處進行屬性值訪問時,通常需要檢查中間節點是否存在:


var street = user.address && user.address.street;

許多 API 返回一個對象或 null/undefined,並且可能只想在結果不為 null 時從結果中提取屬性:


var fooInput = myForm.querySelector('input[name=foo]')
var fooValue = fooInput ? fooInput.value : undefined

Optional Chaining 運算符允許開發人員直接用簡單的方式處理這種情況,而不用進行重複性操作,或者使用臨時變數分配中間結果:


var street = user.address?.street
var fooValue = myForm.querySelector('input[name=foo]')?.value

因為是保護訪問屬性鏈時的 null 與 undefined,所以 Optional Chaining 運算符也叫做「安全導航運算符」,TC39 標準中給出的該運算符是「?.」,它的語法可以適用於三種場景:


obj?.prop       // 自判斷靜態屬性訪問
obj?.[expr]     // 自判斷動態訪問
func?.(...args) // 自判斷函數或方法調用

null 判斷合併(Nullish Coalescing)

另一個與 Optional Chaining 很接近的特性是 null 判斷合併(Nullish Coalescing),由特定的 Nullish Coalescing 操作符 ?? 啟用,它也是即將到來的 ECMAScript 特性。

考慮以下代碼:


let x = (foo !== null && foo !== undefined) ?
    foo :
    bar();

如果 foo 不為空並且不等於 undefined,則執行 bar()。它現在可以等效於:


let x = foo ?? bar();

斷言

如果發生意外情況,則有一組特定函數會拋出錯誤,這被稱為斷言。例如 Node.js 有一個專用的 assert 函數:


assert(someValue === 42);

如果 someValue 不等於 42,則 assert 將拋出 AssertionError。

JavaScript 中的斷言通常用於防止傳入不正確的類型,例如:


function multiply(x, y) {
    assert(typeof x === "number");
    assert(typeof y === "number");

    return x * y;
}

不過在 TypeScript 中,會有一些類型問題:


function yell(str) {
    assert(typeof str === "string");

    return str.toUppercase();
    // Oops! We misspelled 'toUpperCase'.
    // Would be great if TypeScript still caught this!
}

替代方法是改寫代碼,以便語言可以對其進行分析,但這不太方便:


function yell(str) {
    if (typeof str !== "string") {
        throw new TypeError("str should have been a string.")
    }
    // Error caught!
    return str.toUppercase();
}

TypeScript 希望以最小的破壞性方式保留現有 JavaScript 結構,因此 TypeScript 3.7 引入了一個稱為「斷言簽名」的新概念,可以對這些斷言函數進行建模。

第一種斷言簽名對 Node.js assert 的執行方式進行建模,它確保在包含範圍的其餘部分中,無論檢查什麼條件都必須為真。


function assert(condition: any, msg?: string): asserts condition {
    if (!condition) {
        throw new AssertionError(msg)
    }
}

assert condition 表示,如果 assert 返回,則傳遞給 condition 參數的任何內容都必須為 true(否則會引發錯誤),這意味著對於其餘範圍,該條件必須是 true。

以前邊的 yell 為例,確實可以捕獲到類型錯誤:


function yell(str) {
    assert(typeof str === "string");

    return str.toUppercase();
    //         ~~~~~~~~~~~
    // error: Property 'toUppercase' does not exist on type 'string'.
    //        Did you mean 'toUpperCase'?
}

function assert(condition: any, msg?: string): asserts condition {
    if (!condition) {
        throw new AssertionError(msg)
    }
}

另一種斷言簽名不檢查條件,而是告訴 TypeScript 特定的變數或屬性具有不同的類型。


function assertIsString(val: any): asserts val is string {
    if (typeof val !== "string") {
        throw new AssertionError("Not a string!");
    }
}

這裡的 assert val is string,確保在對 assertIsString 進行任何調用之後,傳入的任何變數都將是字元串。


function yell(str: any) {
    assertIsString(str);

    // Now TypeScript knows that 'str' is a 'string'.

    return str.toUppercase();
    //         ~~~~~~~~~~~
    // error: Property 'toUppercase' does not exist on type 'string'.
    //        Did you mean 'toUpperCase'?
}

這些斷言簽名與編寫類型謂詞簽名非常相似:


function isString(val: any): val is string {
    return typeof val === "string";
}

function yell(str: any) {
    if (isString(str)) {
        return str.toUppercase();
    }
    throw "Oops!";
}

類似類型謂詞簽名,這些斷言簽名也具有很強的表現力,可以用這些表達一些相當複雜的邏輯:


function assertIsDefined<T>(val: T): asserts val is NonNullable<T> {
    if (val === undefined || val === null) {
        throw new AssertionError(
            `Expected 'val' to be defined, but received ${val}`
        );
    }
}

此外還有其它新特性與特性增強,詳情查看更新說明:

https://devblogs.microsoft.com/typescript/announcing-typescript-3-7

另外,作為更新的一部分,TypeScript 官網還有一個遊樂場(Playground)可以體驗所有新特性:

https://www.typescriptlang.org/play/index.html?#show-whatisnew





[admin ]

來源:OsChina
連結:https://www.oschina.net/news/111212/typescript-3-7-released
TypeScript 3.7 發布,帶來 Optional Chaining 等特性已經有24次圍觀

http://coctec.com/news/all/show-post-219178.html