Dekorator nima? — experimentalDecorators, metadata reflection

~20 daq · TypeScript · Dekoratorlar

NestJS da @Controller(), @Get(), @Injectable() kabi belgilar — bular dekoratorlar. TypeScript da funksiyani yozmasdan, class yoki metodga maxsus xatti-harakat qo'shish imkoni.


Dekorator nima?

Dekorator — class, metod, xususiyat yoki parametrga qo'yiladigan maxsus funksiya. @ belgisi bilan yoziladi:

@Logla
class Xizmat {
  @Keshla
  ma_lumotOl(): string { return "..."; }
}

@Logla va @Keshla — funksiyalar. Class yoki metod yaratilganda avtomatik chaqiriladi.


Yoqish — tsconfig.json

Dekoratorlar hali eksperimental — yoqish kerak:

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

Oddiy dekorator — funksiya

function Logla(target: Function) {
  console.log(`Class yaratildi: ${target.name}`);
}

@Logla
class Foydalanuvchi {
  constructor(public ism: string) {}
}
// Console: "Class yaratildi: Foydalanuvchi"

Dekorator — class ta'rifi bajarilganda (instance yaratilganda emas) chaqiriladi.


Dekorator factory — parametr bilan

Dekorator parametr qabul qilishi uchun — funksiya qaytaruvchi funksiya:

function Log(daraja: "info" | "warn" | "error") {
  return function(target: Function) {
    console.log(`[${daraja}] ${target.name}`);
  };
}

@Log("info")
class UserService {}

@Log("warn")
class OldService {}

Dekorator tartibi

Bir classda bir nechta dekorator — pastdan yuqoriga bajariladi:

@Birinchi   // 2-bajariladi
@Ikkinchi   // 1-bajariladi
class MyClass {}

reflect-metadata

emitDecoratorMetadata: true bilan TypeScript tur ma'lumotlarini saqlaydi. NestJS, TypeORM bu ma'lumotlardan foydalanadi:

npm install reflect-metadata
import "reflect-metadata";

function LogMeta(target: any, key: string) {
  const tur = Reflect.getMetadata("design:type", target, key);
  console.log(`${key}: ${tur.name}`);
}

class Misol {
  @LogMeta
  ism: string = "";

  @LogMeta
  yosh: number = 0;
}
// ism: String
// yosh: Number

Dekorator turlari

Class dekorator      — class ga qo'yiladi      @Controller()
Method dekorator     — metodga                  @Get("/")
Property dekorator   — xususiyatga              @Column()
Parameter dekorator  — parametrga               @Body()
Accessor dekorator   — getter/setter ga          @Transform()

Xulosa

// tsconfig.json
"experimentalDecorators": true
"emitDecoratorMetadata": true

// Oddiy dekorator
function Logla(target: Function) { console.log(target.name); }
@Logla
class MyClass {}

// Factory (parametr bilan)
function Role(rol: string) {
  return (target: Function) => { /* ... */ };
}
@Role("admin")
class AdminService {}

// Tartib: pastdan yuqoriga
@A @B class X {}  // B, keyin A

Keyingi dars

54-dars: Class dekorator — sinfni o'zgartirish va kengaytirish