TypeScript 進階:初識裝飾器

前言
裝飾器(Decorators)是一個強大且靈活的 TypeScript 特性,它允許我們在類別和類別成員的定義上進行修飾、擴展和修改。這個功能在許多框架中廣泛應用,尤其是在 Angular、NestJS 等依賴裝飾器進行依賴注入的框架中。
在 TypeScript 5 之前,裝飾器還是一個實驗性功能,與現在 TypeScript 5 的裝飾器撰寫方式差異很大,這一篇會先介紹舊版的裝飾器基本使用方式。
什麼是裝飾器?
裝飾器是一種用來修飾類別、屬性或方法的特殊語法。裝飾器本質上是一個函數,允許我們在類別層級或成員層級上執行某些邏輯,例如記錄操作、修改屬性值,甚至動態添加功能。
在使用裝飾器之前,必須在 tsconfig.json 中啟用它。裝飾器是 TypeScript 的一個實驗性語法,啟用方法如下:
{
"compilerOptions": {
// ...other config
"experimentalDecorators": true
}
}這段設定會允許 TypeScript 編譯器理解並編譯裝飾器語法。
如果沒設定,除了編譯器裝飾器的地方可能會飄紅毛毛蟲外,在執行編譯時,也會有錯誤訊息顯示出來,如下圖。

裝飾器的基本結構
前面有提到,裝飾器是要使用在類別或類別的成員上,所以我們先實作一個簡單的類別,而裝飾器本質上是一個高階函數,它接收目標類別、屬性或方法上的資料,並可以進行更多操作。最基本的裝飾器範例如下:
class Person {
@watchValue
name: string = '阿毛'
constructor() {
console.log('初始化 Person')
}
}
function watchValue(target: any, key: string) {
console.log('調用 watchValue 裝飾器')
}
const person = new Person()執行順序
進行編譯過後執行,會發現當裝飾器會先被執行過一次,接著實例化才會執行 constructor 的部分。
調用 watchValue 裝飾器
初始化 Person實作裝飾器功能
我們已經知道了如何使用裝飾器了,接下來要介紹如何實作裝飾器的功能,我們可以利用泛型的方式來定義參數的型別,屬性裝飾器會傳兩個參數,分別為 target(被裝飾類別的建構子) 與 key(被裝飾類別的屬性名稱)
function watchValue<T, K extends keyof T & string>(target: T, key: K) {
console.log('調用 watchValue 裝飾器')
let value = target[key]
const getter = () => value
const setter = (newValue: T[K]) => {
console.log(`設置 ${key} 屬性值從 ${value} 改為 ${newValue}`)
value = newValue
}
Object.defineProperty(target, key, {
get: getter,
set: setter,
configurable: true,
enumerable: true,
})
}
const person = new Person()
person.name = 'Mao'在這個範例中,watchValue 裝飾器透過 Object.defineProperty 改變屬性的行為,使我們能夠監聽並記錄屬性值的變化。當執行這段代碼時,控制台會輸出:
調用 watchValue 裝飾器
設置 name 屬性值從 undefined 改為 阿毛
初始化 Person
設置 name 屬性值從 阿毛 改為 Mao總結
本文介紹了如何使用 TypeScript 5 之前的裝飾器,在實際應用中,裝飾器能幫助我們在框架開發、資料管理和依賴注入等多種情境中實現高效的功能擴展。未來進一步探討類別裝飾器、方法裝飾器、參數裝飾器…等其他的裝飾器,以及如何運用 TypeScript 5 新的裝飾器標準來進行更靈活的開發。
參考資料
Related Posts
TypeScript 後記
終於完成連續三十天的鐵人賽文章撰寫!距離我第一次參加鐵人賽已經三年之久了。這次參加主要是因為朋友邀請一起參賽,同時我自己也想藉此機會深入了解 TypeScript 5 的新功能,強迫自己透過寫作來吸收知識。
TypeScript 實戰:製作 npm Package
在開發專案時,經常會遇到跨專案共用邏輯或工具的情況,例如常用的 logger 或驗證工具。如果每次都從一個專案複製貼上到另一個專案,難免會出現版本不同步或維護困難的問題。為了解決這類問題,我們可以將這些共用邏輯獨立成為 npm 套件,以便在多個專案中重複使用。
TypeScript 實戰:前端表單與串接 API
在現代前端開發中,與後端進行資料交換是常見的需求。透過 HTTP 請求,我們可以將資料送出並取得結果。這篇文章將介紹如何使用 TypeScript 實作前端表單與串接 API,並展示如何將這些功能結合到 React 應用中。同時,文章還會介紹如何解決跨域問題(CORS),以便讓前後端能順利溝通。
Johnson Mao
A passionate software engineer and blogger sharing thoughts on technology, AI, and development.