裝飾器是 ECMAScript 的一項(xiàng)新功能,允許我們以可復(fù)用的方式自定義類及其成員。
考慮以下代碼:
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
greet() {
console.log(`Hello, my name is ${this.name}.`);
}
}
const p = new Person("Ray");
p.greet();
greet
方法很簡(jiǎn)單,但假設(shè)它更復(fù)雜,比如包含異步邏輯、遞歸或副作用。無(wú)論具體實(shí)現(xiàn)如何,我們可能希望通過(guò)添加 console.log
調(diào)用來(lái)調(diào)試 greet
。
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
greet() {
console.log("LOG: Entering method.");
console.log(`Hello, my name is ${this.name}.`);
console.log("LOG: Exiting method.");
}
}
這種模式很常見。如果能有一種方法為每個(gè)方法添加這樣的日志記錄功能就好了。這就是裝飾器的作用。
我們可以編寫一個(gè)名為 loggedMethod
的函數(shù),如下所示:
function loggedMethod(originalMethod: any, _context: any) {
function replacementMethod(this: any, ...args: any[]) {
console.log("LOG: Entering method.");
const result = originalMethod.call(this, ...args);
console.log("LOG: Exiting method.");
return result;
}
return replacementMethod;
}
現(xiàn)在,我們可以使用 loggedMethod
來(lái)裝飾 greet
方法:
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
@loggedMethod
greet() {
console.log(`Hello, my name is ${this.name}.`);
}
}
const p = new Person("Ray");
p.greet();
// 輸出:
// LOG: Entering method.
// Hello, my name is Ray.
// LOG: Exiting method.
我們還可以利用上下文對(duì)象中的信息來(lái)打印被裝飾方法的名稱:
function loggedMethod(originalMethod: any, context: ClassMethodDecoratorContext) {
const methodName = String(context.name);
function replacementMethod(this: any, ...args: any[]) {
console.log(`LOG: Entering method '${methodName}'.`);
const result = originalMethod.call(this, ...args);
console.log(`LOG: Exiting method '${methodName}'.`);
return result;
}
return replacementMethod;
}
裝飾器還可以用于屬性、getter、setter 和自動(dòng)訪問(wèn)器,甚至可以裝飾類本身。
const
類型參數(shù)當(dāng)推斷對(duì)象的類型時(shí),TypeScript 通常會(huì)選擇一個(gè)通用的類型。例如,names
的推斷類型是 string[]
:
type HasNames = { names: readonly string[] };
function getNamesExactly<T extends HasNames>(arg: T): T["names"] {
return arg.names;
}
// 推斷類型:string[]
const names = getNamesExactly({ names: ["Alice", "Bob", "Eve"] });
在 TypeScript 5.0 中,你可以在類型參數(shù)聲明中添加 const
修飾符,使 const
類似的推斷成為默認(rèn)行為:
type HasNames = { names: readonly string[] };
function getNamesExactly<const T extends HasNames>(arg: T): T["names"] {
return arg.names;
}
// 推斷類型:readonly ["Alice", "Bob", "Eve"]
const names = getNamesExactly({ names: ["Alice", "Bob", "Eve"] });
extends
中支持多個(gè)配置文件當(dāng)管理多個(gè)項(xiàng)目時(shí),有一個(gè)基礎(chǔ)配置文件供其他 tsconfig.json
文件擴(kuò)展會(huì)很有幫助。TypeScript 5.0 現(xiàn)在允許 extends
字段接受多個(gè)條目。例如:
{
"extends": ["./tsconfig1.json", "./tsconfig2.json"],
"compilerOptions": {
// ...
}
}
TypeScript 5.0 通過(guò)為每個(gè)計(jì)算成員創(chuàng)建唯一類型,使所有枚舉成為聯(lián)合枚舉。這意味著所有枚舉現(xiàn)在都可以被縮小范圍,并且它們的成員也可以作為類型引用。
TypeScript 4.7 引入了 node16
和 nodenext
選項(xiàng),用于其 --module
和 --moduleResolution
設(shè)置。TypeScript 現(xiàn)在引入了一種新的策略:--moduleResolution bundler
。如果你使用的是現(xiàn)代捆綁器,如 Vite、esbuild、swc、Webpack、Parcel 等,新的 bundler
選項(xiàng)應(yīng)該非常適合你。
--allowImportingTsExtensions
允許 TypeScript 文件使用 TypeScript 特定的擴(kuò)展(如 .ts
、.mts
或 .tsx
)相互導(dǎo)入。
--resolvePackageJsonExports
強(qiáng)制 TypeScript 在從 node_modules
中的包讀取時(shí),咨詢 package.json
文件中的 exports
字段。
--resolvePackageJsonImports
強(qiáng)制 TypeScript 在從文件開始以 #
的查找中咨詢 package.json
文件中的 imports
字段。
--allowArbitraryExtensions
允許導(dǎo)入路徑以未知的 JavaScript 或 TypeScript 文件擴(kuò)展結(jié)束。
--customConditions
指定在 TypeScript 從 package.json
的 exports
或 imports
字段解析時(shí)應(yīng)成功的其他條件。
TypeScript 5.0 引入了一個(gè)新選項(xiàng) --verbatimModuleSyntax
,使導(dǎo)入和導(dǎo)出的規(guī)則更加簡(jiǎn)單:任何沒(méi)有 type
修飾符的導(dǎo)入或?qū)С龆紩?huì)保留,而使用 type
修飾符的導(dǎo)入或?qū)С鰧⒈煌耆珓h除。
export type *
TypeScript 5.0 添加了對(duì) export type * as ns from "module"
和 export type * from "module"
的支持。
@satisfies
支持TypeScript 5.0 在 JSDoc 中支持新的 @satisfies
標(biāo)簽,確保表達(dá)式的類型兼容,而不影響其自身類型。
@overload
支持TypeScript 5.0 允許在 JSDoc 中使用 @overload
標(biāo)簽聲明函數(shù)的重載。
--build
下傳遞特定于 emit 的標(biāo)志TypeScript 現(xiàn)在允許在 --build
模式下傳遞以下標(biāo)志:
--declaration
--emitDeclarationOnly
--declarationMap
--sourceMap
--inlineSourceMap
TypeScript 現(xiàn)在默認(rèn)檢測(cè)大小寫敏感性,以解決在排序?qū)牒蛯?dǎo)出時(shí)的不同解釋問(wèn)題。
switch
/case
補(bǔ)全在編寫 switch
語(yǔ)句時(shí),TypeScript 會(huì)檢測(cè)被檢查值是否具有字面量類型,并提供補(bǔ)全以涵蓋每個(gè)未覆蓋的 case
。
TypeScript 5.0 在代碼結(jié)構(gòu)、數(shù)據(jù)結(jié)構(gòu)和算法實(shí)現(xiàn)方面進(jìn)行了大量改進(jìn),使整個(gè)體驗(yàn)更快,安裝包也更小。
TypeScript 現(xiàn)在針對(duì) ECMAScript 2018。對(duì)于 Node 用戶,這意味著至少需要 Node.js 10 及更高版本。
在 TypeScript 5.0 中,我們遷移到模塊,刪除了一些不必要的接口,并進(jìn)行了一些正確性改進(jìn)。
在 5.0 中,這也將應(yīng)用于關(guān)系運(yùn)算符 >
、<
、<=
和 >=
。
TypeScript 5.0 清理了一些長(zhǎng)期存在的 enum
問(wèn)題,并減少了理解各種 enum
類型所需的概念數(shù)量。
TypeScript 5.0 在 --experimentalDecorators
下對(duì)裝飾器進(jìn)行更準(zhǔn)確的類型檢查。
在 TypeScript 5.0 中,我們棄用了以下設(shè)置和設(shè)置值:
--target: ES3
--out
--noImplicitUseStrict
--keyofStringsOnly
--suppressExcessPropertyErrors
--suppressImplicitAnyIndexErrors
--noStrictGenericChecks
--charset
--importsNotUsedAsValues
--preserveValueImports
prepend
這些配置將繼續(xù)被允許,直到 TypeScript 5.5,屆時(shí)它們將被完全刪除。
更多建議: