TypeScript 3.3來了!快看看有什麼新功能

前端先鋒發表於2019-01-23

翻譯:瘋狂的技術宅 原文:github.com/Microsoft/T…

改進了呼叫聯合型別的行為

在TypeScript的早期版本中,不同的聯合型別如果想互相訪問其取值,它們引數的取值列表必須完全一致才行。

type Fruit = "apple" | "orange";
type Color = "red" | "orange";

type FruitEater = (fruit: Fruit) => number;     // 吃水果並對它們排名
type ColorConsumer = (color: Color) => string;  // 處理顏色並對其進行描述

declare let f: FruitEater | ColorConsumer;

// Cannot invoke an expression whose type lacks a call signature.
// 無法呼叫這個表示式,因為缺少呼叫簽名型別。
// Type 'FruitEater | ColorConsumer' has no compatible call signatures.ts(2349)
// 型別 'FruitEater | ColorConsumer' 沒有相容的呼叫簽名.ts(2349)
f("orange");
複製程式碼

不管怎樣,在上面的例子中,FruitEaterColorConsumer 都應該能夠接受字串"orange",並返回 numberstring 型別才對。

在TypeScript 3.3中,下面這段程式碼將不再會報錯。

type Fruit = "apple" | "orange";
type Color = "red" | "orange";

type FruitEater = (fruit: Fruit) => number;     // 吃水果並對它們排名
type ColorConsumer = (color: Color) => string;  // 處理顏色並對其進行描述

declare let f: FruitEater | ColorConsumer;

f("orange"); // 可以正常工作!將返回一個'number | string'.

f("apple");  // error - Argument of type '"red"' is not assignable to parameter of type '"orange"'.

f("red");    // error - Argument of type '"red"' is not assignable to parameter of type '"orange"'.
複製程式碼

在TypeScript 3.3中,這些引數會互相交織在一起然後建立新簽名。

在上面的例子中, fruitcolor 的引數列表會被交叉到一起產生新的 Fruit&Color 型別的引數。 Fruit & Color會處理為 ("apple" | "orange") & ("red" | "orange") ,它等同於("apple" & "red") | ("apple" & "orange") | ("orange" & "red") | ("orange" & "orange")。 那些不可能的組合被處理成 never,到最後留下了 "orange" & "orange" 這個組合,結果只能是 "orange"

注意 當聯合中最多隻有一個型別具有多個過載時,這種新行為才會出現,並且聯合中最多隻能有一個型別具有通用簽名。 這意味著 number[] | string[]這種形式 ,在 map (通用)這樣的方法中仍然不可以呼叫。

另一方面,在 forEach 這樣的方法中現在可以呼叫,但是在 noImplicitAny 下可能存在一些問題。

interface Dog {
    kind: "dog"
    dogProp: any;
}
interface Cat {
    kind: "cat"
    catProp: any;
}

const catOrDogArray: Dog[] | Cat[] = [];

catOrDogArray.forEach(animal => {
    //                ~~~~~~ error!
    // 引數'animal'隱式含有有'any'型別。
});
複製程式碼

在TypeScript 3.3中,這仍然很嚴格,新增顯式型別註釋將解決這個問題。

interface Dog {
    kind: "dog"
    dogProp: any;
}
interface Cat {
    kind: "cat"
    catProp: any;
}

const catOrDogArray: Dog[] | Cat[] = [];
catOrDogArray.forEach((animal: Dog | Cat) => {
    if (animal.kind === "dog") {
        animal.dogProp;
        // ...
    }
    else if (animal.kind === "cat") {
        animal.catProp;
        // ...
    }
});
複製程式碼

使用 --build --watch 檢查複合專案的增量檔案

TypeScript 3.0 引入了一個用於構建過程的被稱為“複合專案”的新功能。 其目的之一是確保使用者可以將大型專案拆分為更小的部分,從而能夠快速構建,同時保留專案結構,而不會影響現有的 TypeScript 體驗。 正式因為有了複合專案,TypeScript 可以用 --build 模式僅重新編譯部分專案和依賴項集。 您可以把它視為對專案間構建的優化。

TypeScript 2.7還引入了 --watch 模式,通過新的增量“構建器”API進行構建。 該模式只重新檢查和傳送被修改的,可能會影響型別檢查的原始碼檔案和依賴。 您可以將其視為對專案內構建的優化。

在3.3版本之前,在使用 --build --watch 構建複合專案時,實際上並沒有使用這種監視增量檔案的基礎結構。 在 --build --watch 模式下,如果一個專案中有了更新,將會強制完全重新構建該專案,而不是檢查專案中有哪些檔案受到影響。

在TypeScript 3.3中, --build 模式的 --watch 標誌也可以利用增量檔案機制進行監視了。 這可能意味著在 --build --watch 模式下構建速度能將會更快。 在我們的測試中,此功能使--build --watch 的構建時間比原來縮短了50%到75%。 您可以閱讀與檔案修改時的原始拉取請求相關的更多內容來檢視這些資料,我們相信大多數使用複合專案的使用者將會在此處得到更好的體驗。

歡迎關注京程一燈公眾號:jingchengyideng,獲取更多幹貨內容哦~

相關文章