自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

TypeScript 5.4 正式發(fā)布,一起來看看該版本帶來了那些更新

開發(fā) 前端
TypeScript 5.4 將是這些已廢棄選項和行為按預期運作的最后一個版本。在預計于 2024 年 6 月發(fā)布的 TypeScript 5.5 中,這些選項和行為將變成嚴格的錯誤,使用它們的代碼將需要進行遷移以避免編譯錯誤。

3 月 6 日,TypeScript 發(fā)布了 v5.4 版本,該版本帶來了以下更新:

  • 類型縮小會在閉包中保留
  • 引入新的實用程序類型 NoInfer<T>
  • 新增Object.groupBy 和 Map.groupBy
  • 新的模塊解析選項
  • 新的模塊導入檢查機制
  • TypeScript 5.5 即將棄用的功能

類型縮小會在閉包中保留

TypeScript 通過類型縮小來優(yōu)化代碼,但在閉包中并不總是保留這些縮小后的類型。從TypeScript 5.4開始,當在非提升函數(shù)中使用參數(shù)或let變量時,類型檢查器會查找最后的賦值點,從而智能地進行類型縮小。然而,如果變量在嵌套函數(shù)中被重新分配,即使這種分配不影響其類型,也會使閉包中的類型細化無效。

// TypeScript的類型縮小在閉包中通常不保留  
function exampleFunction(input: string | number) {  
    if (typeof input === "string") {  
        input = parseInt(input); // 假設想要將字符串轉(zhuǎn)為數(shù)字  
    }  
  
    return () => {  
        // 在這里,TypeScript不知道input是string還是number  
        // 因為在閉包創(chuàng)建后,input可能已經(jīng)被修改  
        console.log(input.toString()); // 錯誤!'input'可能是number,沒有toString方法  
    };  
}

TypeScript 5.4后,當在閉包外部對變量進行最后一次賦值時,類型縮小會在閉包中保留:

function improvedFunction(input: string | number) {  
    let value;  
    if (typeof input === "string") {  
        value = parseInt(input);  
    } else {  
        value = input;  
    }  
  
    return () => {  
        // 在這里,TypeScript知道value是number,因為這是在閉包創(chuàng)建后的最后一次賦值  
        console.log(value.toString()); // 正確!因為現(xiàn)在我們知道value是number  
    };  
}

引入新的實用程序類型 NoInfer

TypeScript的泛型函數(shù)能夠根據(jù)傳入的參數(shù)自動推斷類型。但在某些情況下,這種自動推斷可能不符合預期,導致不合法的函數(shù)調(diào)用被接受,而合法的調(diào)用卻被拒絕。為了處理這種情況,開發(fā)者通常需要添加額外的類型參數(shù)來約束函數(shù)的行為,確保類型安全。但這種做法可能會使代碼看起來更加復雜,特別是當這些額外的類型參數(shù)在函數(shù)簽名中只使用一次時。

TypeScript 5.4 引入了 NoInfer<T> 實用類型,允許開發(fā)者明確告訴編譯器哪些類型不應該被自動推斷。這避免了不合法的函數(shù)調(diào)用被接受,增強了代碼的類型安全性。

考慮以下函數(shù),它接受一個用戶ID列表和一個可選的默認用戶ID。

function selectUser<U extends string>(userIds: U[], defaultUserId?: U) {  
  // ...  
}  
  
const userIds = ["123", "456", "789"];  
selectUser(userIds, "000"); // 錯誤地被接受,因為"000"不在userIds中

在這個例子中,即使"000"不在userIds數(shù)組中,selectUser函數(shù)的調(diào)用也會被接受,因為TypeScript自動推斷默認用戶ID可以是任何字符串。

TypeScript 5.4 中:

function selectUser<U extends string>(userIds: U[], defaultUserId?: NoInfer<U>) {  
  // ...  
}  
  
const userIds = ["123", "456", "789"];  
selectUser(userIds, "000"); // 正確的錯誤,因為"000"不在userIds中

通過使用 NoInfer<T> 告訴 TypeScript 不要推斷默認用戶ID的類型,從而確保只有當默認用戶ID在userIds數(shù)組中時才接受調(diào)用。這增強了代碼的類型安全性,避免了潛在的錯誤。

新增 Object.groupBy 和 Map.groupBy

TypeScript 5.4 引入了兩個新方法:Object.groupBy 和 Map.groupBy,它們用于根據(jù)特定條件將數(shù)組元素分組。

  • Object.groupBy 返回一個對象,其中每個鍵代表一個分組,對應的值是該分組的元素數(shù)組。
  • Map.groupBy 返回一個`` Map 對象,實現(xiàn)了相同的功能,但允許使用任何類型的鍵。

使用 Object.groupBy 和 Map.groupBy 可以方便地根據(jù)自定義邏輯對數(shù)組進行分組,無需手動創(chuàng)建和填充對象或 Map。然而,在使用 Object.groupBy 時,由于對象的屬性名必須是有效的標識符,因此可能無法覆蓋所有情況。此外,這些方法目前僅在 esnext 目標或特定庫設置下可用。

假設有一個學生數(shù)組,每個學生都有姓名和成績。我們想要根據(jù)成績將學生分為“優(yōu)秀”和“及格”兩組。

const students: { name: string, score: number }[] = [  
  { name: "Alice", score: 90 },  
  { name: "Bob", score: 75 },  
  { name: "Charlie", score: 85 },  
  // ...其他學生  
];  
  
const groupedStudents: { excellent: any[], passing: any[] } = {  
  excellent: [],  
  passing: []  
};  
  
for (const student of students) {  
  if (student.score >= 80) {  
    groupedStudents.excellent.push(student);  
  } else {  
    groupedStudents.passing.push(student);  
  }  
}

使用 Array.prototype.groupBy 方法,可以更簡潔地實現(xiàn)相同的功能。

const students: { name: string, score: number }[] = [  
  { name: "Alice", score: 90 },  
  { name: "Bob", score: 75 },  
  { name: "Charlie", score: 85 },  
  // ...其他學生  
];  
  
const groupedStudents = students.groupBy(student => {  
  return student.score >= 80 ? "excellent" : "passing";  
});  
  
// 使用時可以直接訪問分組  
console.log(groupedStudents.get("excellent")); // 輸出優(yōu)秀學生數(shù)組  
console.log(groupedStudents.get("passing")); // 輸出及格學生數(shù)組

在這個例子中,groupBy 方法根據(jù)每個學生的成績將學生數(shù)組分為“優(yōu)秀”和“及格”兩組,并返回一個 Map 對象,其中鍵是分組名稱,值是對應的學生數(shù)組。這種方法更加簡潔且易于理解。

新的模塊解析選項

TypeScript 5.4 引入了一個新的模塊解析選項 bundler,它模擬了現(xiàn)代構(gòu)建工具(如Webpack、Vite 等)確定導入路徑的方式。當與 --module esnext 配合使用時,它允許開發(fā)者使用標準的 ECMAScript 導入語法,但禁止了 import ... = require(...) 這種混合語法。

同時,TypeScript 5.4 還增加了一個名為 preserve 的模塊選項,該選項允許開發(fā)者在 TypeScript 中使用 require(),并更準確地模擬了構(gòu)建工具和其他運行時環(huán)境的模塊查找行為。當設置 module 為 preserve 時,構(gòu)建工具會隱式地成為默認的模塊解析策略,同時啟用 esModuleInterop 和 resolveJsonModule。

假設有一個使用 TypeScript 編寫的項目,并且想從一個名為 my-lib 的庫中導入兩個模塊 moduleA 和 moduleB。這個庫提供了 ES 模塊和 CommonJS 模塊兩種格式。在 TypeScript 配置中,你可能這樣設置:

// tsconfig.json  
{  
  "compilerOptions": {  
    "module": "commonjs",  
    "moduleResolution": "node"  
  }  
}

然后代碼中這樣導入:

import * as moduleA from 'my-lib/moduleA';  
import * as moduleB = require('my-lib/moduleB');

在這種情況下,TypeScript 可能會為兩個導入生成相同的路徑,因為它們都使用了 Node.js 的模塊解析策略。

在 TypeScript 5.4 中,如果想更精確地控制導入的路徑,特別是當庫提供了基于導入語法的不同實現(xiàn)時,可以使用 preserve 模塊選項和構(gòu)建工具模塊解析策略:

// tsconfig.json  
{  
  "compilerOptions": {  
    "module": "preserve",  
    // 隱式設置:  
    // "moduleResolution": "bundler",  
    // "esModuleInterop": true,  
    // "resolveJsonModule": true  
  }  
}

然后,可以這樣編寫代碼:

import * as moduleA from 'my-lib/moduleA'; // 使用 ES 模塊導入  
const moduleB = require('my-lib/moduleB'); // 使用 CommonJS 模塊導入

現(xiàn)在,TypeScript 會根據(jù) my-lib 的 package.json 文件中的 exports 字段來決定使用哪個文件路徑。如果庫為 ES 模塊和 CommonJS 模塊提供了不同的文件,TypeScript 將根據(jù)導入的語法(import 或 require)選擇正確的文件。

這意味著開發(fā)者可以更精細地控制模塊導入的行為,確保與庫的意圖一致,尤其是在處理那些提供條件導出的庫時。

新的模塊導入檢查機制

TypeScript 5.4 引入了新的模塊導入檢查機制,確保導入的屬性與全局定義的 ImportAttributes 接口相匹配。這種檢查提高了代碼的準確性,因為任何不符合該接口的導入屬性都會導致編譯錯誤。

在早期的 TypeScript 版本中,開發(fā)者可以自由地為 import 語句指定任何導入屬性,而不會有嚴格的類型檢查。這可能導致運行時錯誤,因為導入的屬性可能與實際的模塊不匹配。

// 假設存在一個全局的模塊定義,但沒有明確的導入屬性類型  
import * as myModule from 'my-module' with { custom: 'value' };

在上述代碼中,custom 屬性是自由定義的,沒有與任何全局接口或類型進行匹配,這增加了出錯的風險。

在 TypeScript 5.4 及以后的版本中,開發(fā)者必須確保導入屬性與全局定義的 ImportAttributes 接口相符。這確保了類型安全,并減少了潛在的運行時錯誤。

// 全局定義的導入屬性接口  
interface ImportAttributes {  
    validProperty: string;  
}  
  
// 在模塊中導入時,必須使用符合 ImportAttributes 接口的屬性  
import * as myModule from 'my-module' with { validProperty: 'someValue' };  
  
// 下面的導入將引發(fā)錯誤,因為屬性名稱不匹配  
import * as myModule from 'my-module' with { invalidProperty: 'someValue' };  
// 錯誤:屬性 'invalidProperty' 不存在于類型 'ImportAttributes' 中

在這個新版本中,如果開發(fā)者嘗試使用不符合 ImportAttributes 接口的導入屬性,TypeScript 編譯器將拋出錯誤,從而避免了潛在的錯誤。

TypeScript 5.5 即將棄用的功能

TypeScript 5.0 已經(jīng)廢棄了以下選項和行為:

  • charset
  • target: ES3
  • importsNotUsedAsValues
  • noImplicitUseStrict
  • noStrictGenericChecks
  • keyofStringsOnly
  • suppressExcessPropertyErrors
  • suppressImplicitAnyIndexErrors
  • out
  • preserveValueImports
  • 在項目引用中的prepend
  • 隱式OS特定的newLine

為了在 TypeScript 5.0 及更高版本中繼續(xù)使用這些已廢棄的選項和行為,開發(fā)人員必須指定一個新的選項 ignoreDeprecations,并將其值設置為 "5.0"。

注意,TypeScript 5.4 將是這些已廢棄選項和行為按預期運作的最后一個版本。在預計于 2024 年 6 月發(fā)布的 TypeScript 5.5 中,這些選項和行為將變成嚴格的錯誤,使用它們的代碼將需要進行遷移以避免編譯錯誤。因此,建議開發(fā)人員盡早遷移其代碼庫,以避免未來兼容性問題。

責任編輯:姜華 來源: 前端充電寶
相關(guān)推薦

2024-12-06 08:00:51

2024-05-24 08:35:00

Angular 18版本更新

2024-03-21 08:21:34

Java 22Java 語言開發(fā)工具包

2023-10-20 10:11:00

Nuxt 3.8前端

2022-03-18 08:16:51

微軟Windows 11

2022-06-24 06:32:46

iOS 16Beta 2

2021-09-09 08:47:52

Dependency 安全漏洞工具

2021-07-15 05:26:22

Windows 10操作系統(tǒng)微軟

2021-05-14 05:20:45

Windows10操作系統(tǒng)微軟

2021-10-11 08:21:23

@Valuespringspring框架

2024-04-23 10:29:44

SassCSS前端

2022-02-07 13:34:05

冬奧會黑科技機器人

2010-05-10 17:21:26

Unix操作系統(tǒng)

2024-04-09 10:10:23

GridCSS網(wǎng)格

2021-06-11 05:19:19

Windows10操作系統(tǒng)微軟

2022-08-29 15:30:46

TypeScript代碼

2023-10-18 10:10:29

Node.js 21前端

2021-11-17 10:45:58

Chrome 95新特性前端

2021-02-01 08:16:14

ChromeNode.js

2015-11-10 09:57:18

APP流量
點贊
收藏

51CTO技術(shù)棧公眾號