Property dekorator — xususiyatlarni boshqarish

~15 daq · TypeScript · Dekoratorlar

TypeORM da @Column(), @PrimaryGeneratedColumn() — xususiyat dekoratorlari. Ular xususiyat haqida metadata saqlaydi. Class dekorator bu metadata dan foydalanib jadval sxemasini yaratadi.


Property dekorator imzosi

type PropertyDecorator = (
  target:  Object, // prototype
  key:     string  // xususiyat nomi
) => void;

Property dekorator PropertyDescriptor qaytarmaydi — xususiyatni to'g'ridan o'zgartirish cheklanmagan.


Metadata saqlash

const kolonkaMeta: Map<string, string[]> = new Map();

function Kolonka(target: any, key: string) {
  const className = target.constructor.name;
  if (!kolonkaMeta.has(className)) {
    kolonkaMeta.set(className, []);
  }
  kolonkaMeta.get(className)!.push(key);
}

class Foydalanuvchi {
  @Kolonka id:    number = 0;
  @Kolonka ism:   string = "";
  @Kolonka email: string = "";
  parol:          string = ""; // kolonka emas
}

kolonkaMeta.get("Foydalanuvchi"); // ["id", "ism", "email"]

reflect-metadata bilan

import "reflect-metadata";

function Kolonka(target: any, key: string) {
  const tur = Reflect.getMetadata("design:type", target, key);
  Reflect.defineMetadata("kolonka:tur", tur.name, target, key);
}

class Mahsulot {
  @Kolonka nomi:  string = "";
  @Kolonka narxi: number = 0;
}

const m = new Mahsulot();
Reflect.getMetadata("kolonka:tur", m, "nomi");  // "String"
Reflect.getMetadata("kolonka:tur", m, "narxi"); // "Number"

Tekshiruv (validation)

const validatsiyaMeta: Map<string, { min?: number; max?: number }> = new Map();

function Range(min: number, max: number) {
  return function(target: any, key: string) {
    validatsiyaMeta.set(key, { min, max });
  };
}

class Forma {
  @Range(0, 120) yosh: number = 0;
  @Range(5, 100) ism_uzunlik: number = 0;
}

function tekshir(ob: any): string[] {
  const xatolar: string[] = [];
  for (const [key, { min, max }] of validatsiyaMeta) {
    const q = ob[key];
    if (min !== undefined && q < min) xatolar.push(`${key} < ${min}`);
    if (max !== undefined && q > max) xatolar.push(`${key} > ${max}`);
  }
  return xatolar;
}

const f = new Forma();
f.yosh = 150;
tekshir(f); // ["yosh > 120"]

Xulosa

// Imzo
function MyDeco(target: Object, key: string): void { ... }

// Metadata saqlash
function Deko(target: any, key: string) {
  Reflect.defineMetadata("kalit", qiymat, target, key);
}

// O'qish
Reflect.getMetadata("kalit", instans, "xususiyat");

// TypeORM misoli
@Entity()
class User {
  @PrimaryGeneratedColumn() id: number;
  @Column() ism: string;
}

Keyingi dars

57-dars: Parameter dekorator — parametrlarni belgilash