Decorator үндэс
Decorator бол class, method, property-д нэмэлт зан төлөв (behavior) нэмэх тусгай синтакс юм. @ тэмдэгтээр эхэлдэг бөгөөд Angular, NestJS зэрэг алдартай framework-үүд decorator-ийг өргөнөөр ашигладаг.
Decorator нь нэг үгээр хэлбэл — функцийг өөрчлөхгүйгээр түүнд нэмэлт чадвар өгдөг "наалт" юм.
Decorator идэвхжүүлэх
TypeScript-д decorator туршилтын (experimental) горимд байгаа тул tsconfig.json-д идэвхжүүлэх шаардлагатай:
// tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
Эдгээр тохиргоогүйгээр decorator ашиглахад хөрвүүлэгч алдаа заана.
Class decorator
Class decorator нь class-ийн constructor-ийг хүлээн авч, шинэ class буцааж болдог:
// Decorator функц тодорхойлох
function Лог(constructor: Function) {
console.log(`Class үүсгэгдлээ: ${constructor.name}`);
}
function Хөлдөөх(constructor: Function) {
Object.freeze(constructor);
Object.freeze(constructor.prototype);
}
// Decorator хэрэглэх — @ тэмдгийн ард нэр бичнэ
@Лог
@Хөлдөөх
class ХэрэглэгчийнҮйлчилгээ {
нэвтрэх(и_мэйл: string) {
console.log(`${и_мэйл} нэвтэрлээ`);
}
}
// "Class үүсгэгдлээ: ХэрэглэгчийнҮйлчилгээ" гэж хэвлэнэ
const үйлчилгээ = new ХэрэглэгчийнҮйлчилгээ();
Decorator-ууд доороос дээш дарааллаар ажилладаг — @Хөлдөөх эхлээд, дараа нь @Лог.
Method decorator
Method decorator нь тухайн method-ийн ажиллагааг өөрчилж болдог. Хамгийн түгээмэл хэрэглээ нь — readonly болгох, лог бичих, алдааг барих:
// Method decorator — аргументүүд: target, нэр, тодорхойлолт
function Уншихад_Зориулагдсан(
target: object,
propertyKey: string,
descriptor: PropertyDescriptor
) {
descriptor.writable = false; // method-ийг дарж бичихийг хориглоно
return descriptor;
}
function АлдааБарих(
target: object,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const анхныФункц = descriptor.value;
descriptor.value = async function (...аргументууд: unknown[]) {
try {
return await анхныФункц.apply(this, аргументууд);
} catch (алдаа) {
console.error(`${propertyKey} дотор алдаа гарлаа:`, алдаа);
throw алдаа;
}
};
return descriptor;
}
class ДатабааcийнҮйлчилгээ {
@АлдааБарих
async хэрэглэгчАвах(id: string) {
// алдаа гарвал @АлдааБарих автоматаар барина
const хариу = await fetch(`/api/users/${id}`);
return хариу.json();
}
@Уншихад_Зориулагдсан
мэндчилэх() {
return "Сайн уу!";
}
}
const үйлчилгээ = new ДатабааcийнҮйлчилгээ();
// үйлчилгээ.мэндчилэх = () => "Өөр зүйл"; // Алдаа! readonly
Property decorator
Property decorator нь class-ийн шинж чанарт хэрэглэгдэнэ:
// Утгыг автоматаар хэвлэдэг property decorator
function Хяналт(target: object, propertyKey: string) {
let утга: unknown;
Object.defineProperty(target, propertyKey, {
get() {
return утга;
},
set(шинэУтга: unknown) {
console.log(`${propertyKey}: ${утга} → ${шинэУтга}`);
утга = шинэУтга;
},
});
}
class ХэрэглэгчийнПрофайл {
@Хяналт
нэр: string = "";
@Хяналт
xp: number = 0;
}
const профайл = new ХэрэглэгчийнПрофайл();
профайл.нэр = "Болд"; // "нэр: → Болд" гэж хэвлэнэ
профайл.xp = 100; // "xp: 0 → 100" гэж хэвлэнэ
Дараагийн хичээлд:
emitDecoratorMetadata болон Reflect Metadata API-г ашиглан decorator-д төрлийн мэдээлэл хэрхэн нэмэх тухай сурна.