裝飾器是 ECMAScript 的一項新功能,允許我們以可復(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
方法很簡單,但假設(shè)它更復(fù)雜,比如包含異步邏輯、遞歸或副作用。無論具體實現(xiàn)如何,我們可能希望通過添加 console.log
調(diào)用來調(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.");
}
}
這種模式很常見。如果能有一種方法為每個方法添加這樣的日志記錄功能就好了。這就是裝飾器的作用。
我們可以編寫一個名為 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
來裝飾 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.
我們還可以利用上下文對象中的信息來打印被裝飾方法的名稱:
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 和自動訪問器,甚至可以裝飾類本身。
const
類型參數(shù)當(dāng)推斷對象的類型時,TypeScript 通常會選擇一個通用的類型。例如,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
中支持多個配置文件當(dāng)管理多個項目時,有一個基礎(chǔ)配置文件供其他 tsconfig.json
文件擴展會很有幫助。TypeScript 5.0 現(xiàn)在允許 extends
字段接受多個條目。例如:
{
"extends": ["./tsconfig1.json", "./tsconfig2.json"],
"compilerOptions": {
// ...
}
}
TypeScript 5.0 通過為每個計算成員創(chuàng)建唯一類型,使所有枚舉成為聯(lián)合枚舉。這意味著所有枚舉現(xiàn)在都可以被縮小范圍,并且它們的成員也可以作為類型引用。
TypeScript 4.7 引入了 node16
和 nodenext
選項,用于其 --module
和 --moduleResolution
設(shè)置。TypeScript 現(xiàn)在引入了一種新的策略:--moduleResolution bundler
。如果你使用的是現(xiàn)代捆綁器,如 Vite、esbuild、swc、Webpack、Parcel 等,新的 bundler
選項應(yīng)該非常適合你。
--allowImportingTsExtensions
允許 TypeScript 文件使用 TypeScript 特定的擴展(如 .ts
、.mts
或 .tsx
)相互導(dǎo)入。
--resolvePackageJsonExports
強制 TypeScript 在從 node_modules
中的包讀取時,咨詢 package.json
文件中的 exports
字段。
--resolvePackageJsonImports
強制 TypeScript 在從文件開始以 #
的查找中咨詢 package.json
文件中的 imports
字段。
--allowArbitraryExtensions
允許導(dǎo)入路徑以未知的 JavaScript 或 TypeScript 文件擴展結(jié)束。
--customConditions
指定在 TypeScript 從 package.json
的 exports
或 imports
字段解析時應(yīng)成功的其他條件。
TypeScript 5.0 引入了一個新選項 --verbatimModuleSyntax
,使導(dǎo)入和導(dǎo)出的規(guī)則更加簡單:任何沒有 type
修飾符的導(dǎo)入或?qū)С龆紩A?,而使?type
修飾符的導(dǎo)入或?qū)С鰧⒈煌耆珓h除。
export type *
TypeScript 5.0 添加了對 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)檢測大小寫敏感性,以解決在排序?qū)牒蛯?dǎo)出時的不同解釋問題。
switch
/case
補全在編寫 switch
語句時,TypeScript 會檢測被檢查值是否具有字面量類型,并提供補全以涵蓋每個未覆蓋的 case
。
TypeScript 5.0 在代碼結(jié)構(gòu)、數(shù)據(jù)結(jié)構(gòu)和算法實現(xiàn)方面進(jìn)行了大量改進(jìn),使整個體驗更快,安裝包也更小。
TypeScript 現(xiàn)在針對 ECMAScript 2018。對于 Node 用戶,這意味著至少需要 Node.js 10 及更高版本。
在 TypeScript 5.0 中,我們遷移到模塊,刪除了一些不必要的接口,并進(jìn)行了一些正確性改進(jìn)。
在 5.0 中,這也將應(yīng)用于關(guān)系運算符 >
、<
、<=
和 >=
。
TypeScript 5.0 清理了一些長期存在的 enum
問題,并減少了理解各種 enum
類型所需的概念數(shù)量。
TypeScript 5.0 在 --experimentalDecorators
下對裝飾器進(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,屆時它們將被完全刪除。
更多建議: