装饰器是一种特殊类型的声明,可以附加到类声明、方法、属性或参数上,以修改类的行为。装饰器使用
@expression语法,其中expression是一个函数,在运行时被调用。
装饰器是一个函数,接收目标对象作为参数,返回修改后的对象或新对象。装饰器可以在不修改原有代码的情况下,扩展类的功能。
function logged(target: any) {
console.log(`${target.name} 已被装饰`)
}
@logged
class User {
constructor(public name: string) {}
}
TypeScript 支持以下类型的装饰器:
使用装饰器需要在 tsconfig.json 中启用。
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
experimentalDecorators 启用装饰器,emitDecoratorMetadata 启用装饰器元数据。
类装饰器应用于类构造函数,可以修改或替换类定义。
function sealed(target: any) {
Object.seal(target)
Object.seal(target.prototype)
}
@sealed
class User {
constructor(public name: string) {}
}
类装饰器可以返回一个新的类。
function extend<T extends { new (...args: any[]): {} }>(target: T) {
return class extends target {
createdAt = new Date()
}
}
@extend
class User {
constructor(public name: string) {}
}
const user = new (User as any)("张三")
console.log(user.createdAt)
方法装饰器应用于方法,可以修改方法的行为。
function log(
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const original = descriptor.value
descriptor.value = function (...args: any[]) {
console.log(`调用 ${propertyKey},参数: ${args}`)
return original.apply(this, args)
}
return descriptor
}
class Calculator {
@log
add(a: number, b: number): number {
return a + b
}
}
const calc = new Calculator()
calc.add(1, 2)
属性装饰器应用于属性,可以修改属性的行为。
function readonly(target: any, propertyKey: string) {
Object.defineProperty(target, propertyKey, {
writable: false
})
}
class User {
@readonly
name: string = "张三"
}
const user = new User()
user.name = "李四"
参数装饰器应用于方法参数,可以记录参数信息。
function required(target: any, propertyKey: string, parameterIndex: number) {
console.log(`${propertyKey} 的第 ${parameterIndex} 个参数是必需的`)
}
class User {
greet(@required name: string): string {
return `你好,${name}`
}
}
装饰器工厂是一个返回装饰器的函数,可以接收参数。
function color(value: string) {
return function (target: any) {
target.prototype.color = value
}
}
@color("red")
class Car {}
const car = new (Car as any)()
console.log(car.color)
装饰器常用于日志、缓存、验证等场景。
function cache(
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const original = descriptor.value
const cacheMap = new Map<string, any>()
descriptor.value = function (...args: any[]) {
const key = JSON.stringify(args)
if (cacheMap.has(key)) {
console.log("从缓存返回")
return cacheMap.get(key)
}
const result = original.apply(this, args)
cacheMap.set(key, result)
return result
}
return descriptor
}
class DataService {
@cache
async fetchData(id: number): Promise<any> {
console.log("请求服务器")
return { id, data: "数据" }
}
}
async function main() {
const service = new DataService()
await service.fetchData(1)
await service.fetchData(1)
}
main()
装饰器是一种特殊类型的声明,可以附加到类、方法、属性或参数上。装饰器使用 @expression 语法,是一个在运行时被调用的函数。TypeScript 支持类装饰器、方法装饰器、属性装饰器、参数装饰器和访问器装饰器。装饰器工厂可以接收参数并返回装饰器。装饰器常用于日志、缓存、验证等场景。