TypeScript dekoratorlarini o'rganing: kod tuzilishini, qayta foydalanish imkoniyatini va qo'llab-quvvatlanuvchanlikni yaxshilash uchun kuchli metadasturlash xususiyati. Amaliy misollar yordamida ulardan samarali foydalanishni o'rganing.
TypeScript Dekoratorlari: Metadasturlash Kuchini Ochish
TypeScript dekoratorlari metadasturlash imkoniyatlari bilan kodingizni kengaytirishning kuchli va nafis usulini taqdim etadi. Ular dizayn vaqtida sinflar, metodlar, xususiyatlar va parametrlarni o'zgartirish va kengaytirish mexanizmini taklif etib, kodingizning asosiy mantig'ini o'zgartirmasdan xatti-harakatlar va annotatsiyalarni qo'shish imkonini beradi. Ushbu blog posti TypeScript dekoratorlarining nozik jihatlariga chuqur kirib boradi va barcha darajadagi dasturchilar uchun keng qamrovli qo'llanmani taqdim etadi. Biz dekoratorlarning nima ekanligini, ular qanday ishlashini, mavjud turlarini, amaliy misollarni va ulardan samarali foydalanish uchun eng yaxshi amaliyotlarni o'rganamiz. Siz TypeScript-ga yangi kirgan bo'lasizmi yoki tajribali dasturchimisiz, ushbu qo'llanma sizni toza, qo'llab-quvvatlanadigan va ifodali kod uchun dekoratorlardan foydalanish bilimiga ega qiladi.
TypeScript Dekoratorlari nima?
Aslida, TypeScript dekoratorlari metadasturlashning bir shaklidir. Ular mohiyatan bir yoki bir nechta argumentlarni (odatda bezatilayotgan narsa, masalan, sinf, metod, xususiyat yoki parametr) qabul qiladigan va uni o'zgartirishi yoki yangi funksionallik qo'shishi mumkin bo'lgan funksiyalardir. Ularni kodingizga biriktiradigan annotatsiyalar yoki atributlar deb o'ylang. Ushbu annotatsiyalar keyinchalik kod haqida metama'lumotlar taqdim etish yoki uning xatti-harakatini o'zgartirish uchun ishlatilishi mumkin.
Dekoratorlar `@` belgisi va undan keyin keladigan funksiya chaqiruvi (masalan, `@dekoratorNomi()`) yordamida aniqlanadi. Dekorator funksiyasi keyin ilovangizning dizayn vaqti bosqichida bajariladi.
Dekoratorlar Java, C# va Python kabi tillardagi shunga o'xshash xususiyatlardan ilhomlangan. Ular asosiy mantig'ingizni toza saqlash va metama'lumotlaringiz yoki o'zgartirish jihatlaringizni maxsus joyda jamlash orqali vazifalarni ajratish va kodni qayta ishlatishni rag'batlantirish usulini taklif qiladi.
Dekoratorlar qanday ishlaydi
TypeScript kompilyatori dekoratorlarni dizayn vaqtida chaqiriladigan funksiyalarga aylantiradi. Dekorator funksiyasiga uzatiladigan aniq argumentlar ishlatilayotgan dekorator turiga (sinf, metod, xususiyat yoki parametr) bog'liq. Keling, har xil turdagi dekoratorlarni va ularning tegishli argumentlarini ko'rib chiqamiz:
- Sinf Dekoratorlari: Sinf e'loniga qo'llaniladi. Ular sinfning konstruktor funksiyasini argument sifatida qabul qiladi va sinfni o'zgartirish, statik xususiyatlar qo'shish yoki sinfni biron bir tashqi tizim bilan ro'yxatdan o'tkazish uchun ishlatilishi mumkin.
- Metod Dekoratorlari: Metod e'loniga qo'llaniladi. Ular uchta argument oladi: sinf prototipi, metod nomi va metod uchun xususiyat deskriptori. Metod dekoratorlari metodni o'zgartirish, metod bajarilishidan oldin yoki keyin funksionallik qo'shish yoki hatto metodni butunlay almashtirish imkonini beradi.
- Xususiyat Dekoratorlari: Xususiyat e'loniga qo'llaniladi. Ular ikkita argument oladi: sinf prototipi va xususiyat nomi. Ular xususiyatning xatti-harakatini o'zgartirishga imkon beradi, masalan, validatsiya yoki standart qiymatlarni qo'shish.
- Parametr Dekoratorlari: Metod e'lonidagi parametrga qo'llaniladi. Ular uchta argument oladi: sinf prototipi, metod nomi va parametr ro'yxatidagi parametr indeksi. Parametr dekoratorlari ko'pincha bog'liqlik inyeksiyasi yoki parametr qiymatlarini tekshirish uchun ishlatiladi.
Samarali dekoratorlar yozish uchun ushbu argument imzolarini tushunish juda muhimdir.
Dekorator Turlari
TypeScript har biri o'ziga xos maqsadga xizmat qiladigan bir nechta turdagi dekoratorlarni qo'llab-quvvatlaydi:
- Sinf Dekoratorlari: Sinfning o'zini o'zgartirish yoki metama'lumot qo'shishga imkon berib, sinflarni bezash uchun ishlatiladi.
- Metod Dekoratorlari: Metod chaqiruvidan oldin yoki keyin xatti-harakat qo'shish yoki hatto metod implementatsiyasini almashtirish imkonini berib, metodlarni bezash uchun ishlatiladi.
- Xususiyat Dekoratorlari: Validatsiya, standart qiymatlar qo'shish yoki xususiyatning xatti-harakatini o'zgartirishga imkon berib, xususiyatlarni bezash uchun ishlatiladi.
- Parametr Dekoratorlari: Metod parametrlarini bezash uchun ishlatiladi, ko'pincha bog'liqlik inyeksiyasi yoki parametr validatsiyasi uchun qo'llaniladi.
- Kirish (Accessor) Dekoratorlari: Getter va setterlarni bezatadi. Ushbu dekoratorlar funksional jihatdan xususiyat dekoratorlariga o'xshaydi, lekin maxsus kirishchilarga (accessor) mo'ljallangan. Ular metod dekoratorlari kabi o'xshash argumentlarni qabul qiladi, lekin getter yoki setterga ishora qiladi.
Amaliy Misollar
TypeScript-da dekoratorlardan qanday foydalanishni ko'rsatish uchun ba'zi amaliy misollarni ko'rib chiqamiz.
Sinf Dekoratori Misoli: Vaqt Belgisini Qo'shish
Tasavvur qiling, siz sinfning har bir nusxasiga vaqt belgisini qo'shmoqchisiz. Bunga erishish uchun sinf dekoratoridan foydalanishingiz mumkin:
function addTimestamp<T extends { new(...args: any[]): {} }>(constructor: T) {
return class extends constructor {
timestamp = Date.now();
};
}
@addTimestamp
class MyClass {
constructor() {
console.log('MyClass yaratildi');
}
}
const instance = new MyClass();
console.log(instance.timestamp); // Natija: vaqt belgisi
Ushbu misolda `addTimestamp` dekoratori sinf nusxasiga `timestamp` xususiyatini qo'shadi. Bu asl sinf ta'rifini to'g'ridan-to'g'ri o'zgartirmasdan qimmatli disk raskadrovka yoki audit izi ma'lumotlarini taqdim etadi.
Metod Dekoratori Misoli: Metod Chaqiruvlarini Loglash
Metod chaqiruvlarini va ularning argumentlarini loglash uchun metod dekoratoridan foydalanishingiz mumkin:
function logMethod(target: any, key: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`[LOG] ${key} metodi chaqirildi, argumentlar:`, args);
const result = originalMethod.apply(this, args);
console.log(`[LOG] ${key} metodi qaytardi:`, result);
return result;
};
return descriptor;
}
class Greeter {
@logMethod
greet(message: string): string {
return `Salom, ${message}!`;
}
}
const greeter = new Greeter();
greeter.greet('Dunyo');
// Natija:
// [LOG] greet metodi chaqirildi, argumentlar: [ 'Dunyo' ]
// [LOG] greet metodi qaytardi: Salom, Dunyo!
Ushbu misol `greet` metodi har safar chaqirilganda, uning argumentlari va qaytarilgan qiymati bilan birga log yozadi. Bu murakkabroq ilovalarda disk raskadrovka va monitoring uchun juda foydali.
Xususiyat Dekoratori Misoli: Validatsiya Qo'shish
Quyida asosiy validatsiyani qo'shadigan xususiyat dekoratori misoli keltirilgan:
function validate(target: any, key: string) {
let value: any;
const getter = function () {
return value;
};
const setter = function (newValue: any) {
if (typeof newValue !== 'number') {
console.warn(`[OGOHLANTIRISH] Noto'g'ri xususiyat qiymati: ${key}. Raqam kutilgan edi.`);
return;
}
value = newValue;
};
Object.defineProperty(target, key, {
get: getter,
set: setter,
enumerable: true,
configurable: true,
});
}
class Person {
@validate
age: number; // <- Validatsiyali xususiyat
}
const person = new Person();
person.age = 'abc'; // Ogohlantirishni loglaydi
person.age = 30; // Qiymatni o'rnatadi
console.log(person.age); // Natija: 30
Ushbu `validate` dekoratorida biz tayinlangan qiymatning raqam ekanligini tekshiramiz. Agar bo'lmasa, ogohlantirishni loglaymiz. Bu oddiy misol, lekin u dekoratorlarning ma'lumotlar yaxlitligini ta'minlash uchun qanday ishlatilishini ko'rsatadi.
Parametr Dekoratori Misoli: Bog'liqlik Inyeksiyasi (Soddalashtirilgan)
To'liq bog'liqlik inyeksiyasi freymvorklari ko'pincha murakkabroq mexanizmlardan foydalansa-da, dekoratorlar ham inyektsiya uchun parametrlarni belgilash uchun ishlatilishi mumkin. Ushbu misol soddalashtirilgan ko'rinishdir:
// Bu soddalashtirish va haqiqiy inyeksiyani bajarmaydi. Haqiqiy DI murakkabroq.
function Inject(service: any) {
return function (target: any, propertyKey: string | symbol, parameterIndex: number) {
// Servisni biror joyda saqlash (masalan, statik xususiyatda yoki xaritada)
if (!target.injectedServices) {
target.injectedServices = {};
}
target.injectedServices[parameterIndex] = service;
};
}
class MyService {
doSomething() { /* ... */ }
}
class MyComponent {
constructor(@Inject(MyService) private myService: MyService) {
// Haqiqiy tizimda DI konteyneri bu yerda 'myService'ni hal qilgan bo'lardi.
console.log('MyComponent quyidagi bilan tuzildi:', myService.constructor.name); //Misol
}
}
const component = new MyComponent(new MyService()); // Servisni inyektsiya qilish (soddalashtirilgan).
`Inject` dekoratori parametrni servis talab qiladigan deb belgilaydi. Ushbu misol dekoratorning bog'liqlik inyeksiyasini talab qiladigan parametrlarni qanday aniqlashini ko'rsatadi (lekin haqiqiy freymvork servisni hal qilishni boshqarishi kerak).
Dekoratorlardan Foydalanishning Afzalliklari
- Koddan Qayta Foydalanish: Dekoratorlar sizga umumiy funksionallikni (loglash, validatsiya va avtorizatsiya kabi) qayta ishlatiladigan komponentlarga joylashtirish imkonini beradi.
- Vazifalarni Ajratish: Dekoratorlar sinflaringiz va metodlaringizning asosiy mantig'ini toza va fokuslangan holda saqlab, vazifalarni ajratishga yordam beradi.
- O'qish Osonligi Yaxshilanishi: Dekoratorlar sinf, metod yoki xususiyatning maqsadini aniq ko'rsatib, kodingizni o'qish uchun qulayroq qilishi mumkin.
- Shablon Kodni Kamaytirish: Dekoratorlar kesib o'tuvchi vazifalarni amalga oshirish uchun zarur bo'lgan shablon kod miqdorini kamaytiradi.
- Kengaytiriluvchanlik: Dekoratorlar asl manba fayllarini o'zgartirmasdan kodingizni kengaytirishni osonlashtiradi.
- Metama'lumotlarga Asoslangan Arxitektura: Dekoratorlar sizga metama'lumotlarga asoslangan arxitekturalarni yaratish imkonini beradi, bu yerda kodingizning xatti-harakati annotatsiyalar bilan boshqariladi.
Dekoratorlardan Foydalanishning Eng Yaxshi Amaliyotlari
- Dekoratorlarni Sodda Saqlang: Dekoratorlar odatda qisqa va ma'lum bir vazifaga qaratilgan bo'lishi kerak. Murakkab mantiq ularni tushunish va saqlashni qiyinlashtirishi mumkin.
- Kompozitsiyani Ko'rib Chiqing: Bir xil elementda bir nechta dekoratorlarni birlashtirishingiz mumkin, lekin qo'llash tartibining to'g'riligiga ishonch hosil qiling. (Eslatma: bir xil turdagi elementdagi dekoratorlar uchun qo'llash tartibi pastdan yuqoriga).
- Testlash: Dekoratorlaringizni kutilganidek ishlashini va kutilmagan yon ta'sirlarni keltirib chiqarmasligini ta'minlash uchun ularni sinchkovlik bilan sinab ko'ring. Dekoratorlaringiz tomonidan yaratilgan funksiyalar uchun birlik testlarini yozing.
- Hujjatlashtirish: Dekoratorlaringizni, jumladan ularning maqsadi, argumentlari va har qanday yon ta'sirlarini aniq hujjatlashtiring.
- Ma'noli Nomlarni Tanlang: Kod o'qilishini yaxshilash uchun dekoratorlaringizga tavsiflovchi va ma'lumot beruvchi nomlar bering.
- Haddan Tashqari Foydalanishdan Saqlaning: Dekoratorlar kuchli bo'lsa-da, ulardan haddan tashqari foydalanishdan saqlaning. Ularning afzalliklarini potentsial murakkablik bilan muvozanatlashtiring.
- Bajarilish Tartibini Tushuning: Dekoratorlarning bajarilish tartibiga e'tibor bering. Avval sinf dekoratorlari, so'ngra xususiyat dekoratorlari, keyin metod dekoratorlari va nihoyat parametr dekoratorlari qo'llaniladi. Bir tur ichida qo'llash pastdan yuqoriga qarab amalga oshiriladi.
- Tiplar Xavfsizligi: Dekoratorlaringizda tiplar xavfsizligini ta'minlash uchun har doim TypeScript-ning tip tizimidan samarali foydalaning. Dekoratorlaringizning kutilgan tiplar bilan to'g'ri ishlashini ta'minlash uchun generiklar va tip annotatsiyalaridan foydalaning.
- Moslik: Siz foydalanayotgan TypeScript versiyasidan xabardor bo'ling. Dekoratorlar TypeScript xususiyati bo'lib, ularning mavjudligi va xatti-harakati versiyaga bog'liq. Siz mos keladigan TypeScript versiyasidan foydalanayotganingizga ishonch hosil qiling.
Murakkab Tushunchalar
Dekorator Fabrikalari
Dekorator fabrikalari dekorator funksiyalarini qaytaradigan funksiyalardir. Bu sizga dekoratorlaringizga argumentlar uzatish imkonini beradi, bu ularni yanada moslashuvchan va sozlanuvchan qiladi. Masalan, siz validatsiya qoidalarini belgilash imkonini beradigan validatsiya dekorator fabrikasini yaratishingiz mumkin:
function validate(minLength: number) {
return function (target: any, key: string) {
let value: string;
const getter = function () {
return value;
};
const setter = function (newValue: string) {
if (typeof newValue !== 'string') {
console.warn(`[OGOHLANTIRISH] Noto'g'ri xususiyat qiymati: ${key}. Satr kutilgan edi.`);
return;
}
if (newValue.length < minLength) {
console.warn(`[OGOHLANTIRISH] ${key} kamida ${minLength} belgidan iborat bo'lishi kerak.`);
return;
}
value = newValue;
};
Object.defineProperty(target, key, {
get: getter,
set: setter,
enumerable: true,
configurable: true,
});
};
}
class Person {
@validate(3) // Minimal uzunligi 3 bilan tekshirish
name: string;
}
const person = new Person();
person.name = 'Jo';
console.log(person.name); // Ogohlantirishni loglaydi, qiymatni o'rnatadi.
person.name = 'John';
console.log(person.name); // Natija: John
Dekorator fabrikalari dekoratorlarni ancha moslashuvchan qiladi.
Dekoratorlarni Birlashtirish
Siz bir xil elementga bir nechta dekoratorlarni qo'llashingiz mumkin. Ularning qo'llanilish tartibi ba'zan muhim bo'lishi mumkin. Tartib pastdan yuqoriga (yozilganidek). Masalan:
function first() {
console.log('first(): fabrika baholandi');
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log('first(): chaqirildi');
}
}
function second() {
console.log('second(): fabrika baholandi');
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log('second(): chaqirildi');
}
}
class ExampleClass {
@first()
@second()
method() {}
}
// Natija:
// second(): fabrika baholandi
// first(): fabrika baholandi
// second(): chaqirildi
// first(): chaqirildi
E'tibor bering, fabrika funksiyalari paydo bo'lish tartibida baholanadi, lekin dekorator funksiyalari teskari tartibda chaqiriladi. Agar dekoratorlaringiz bir-biriga bog'liq bo'lsa, ushbu tartibni tushuning.
Dekoratorlar va Metama'lumotlar Refleksiyasi
Dekoratorlar yanada dinamik xatti-harakatlarga erishish uchun metama'lumotlar refleksiyasi bilan (`reflect-metadata` kabi kutubxonalardan foydalanib) birgalikda ishlashi mumkin. Bu sizga, masalan, ish vaqtida (runtime) bezatilgan elementlar haqidagi ma'lumotlarni saqlash va olish imkonini beradi. Bu ayniqsa freymvorklar va bog'liqlik inyeksiyasi tizimlarida foydalidir. Dekoratorlar sinflarni yoki metodlarni metama'lumotlar bilan annotatsiya qilishi mumkin, va keyin refleksiya ushbu metama'lumotlarni topish va ishlatish uchun qo'llanilishi mumkin.
Ommabop Freymvork va Kutubxonalardagi Dekoratorlar
Dekoratorlar ko'plab zamonaviy JavaScript freymvorklari va kutubxonalarining ajralmas qismiga aylandi. Ularning qo'llanilishini bilish sizga freymvork arxitekturasini va uning turli vazifalarni qanday soddalashtirishini tushunishga yordam beradi.
- Angular: Angular bog'liqlik inyeksiyasi, komponent ta'rifi (masalan, `@Component`), xususiyatlarni bog'lash (`@Input`, `@Output`) va boshqalar uchun dekoratorlardan keng foydalanadi. Ushbu dekoratorlarni tushunish Angular bilan ishlash uchun zarurdir.
- NestJS: NestJS, progressiv Node.js freymvorki, modulli va qo'llab-quvvatlanadigan ilovalar yaratish uchun dekoratorlardan keng foydalanadi. Dekoratorlar kontrollerlar, servislar, modullar va boshqa asosiy komponentlarni aniqlash uchun ishlatiladi. U marshrutni aniqlash, bog'liqlik inyeksiyasi va so'rov validatsiyasi uchun dekoratorlardan keng foydalanadi (masalan, `@Controller`, `@Get`, `@Post`, `@Injectable`).
- TypeORM: TypeORM, TypeScript uchun ORM (Obyekt-Relatsion Xaritalash), sinflarni ma'lumotlar bazasi jadvallariga xaritalash, ustunlar va munosabatlarni aniqlash uchun dekoratorlardan foydalanadi (masalan, `@Entity`, `@Column`, `@PrimaryGeneratedColumn`, `@OneToMany`).
- MobX: MobX, holatni boshqarish kutubxonasi, xususiyatlarni kuzatiladigan (`@observable`) va metodlarni harakatlar (`@action`) sifatida belgilash uchun dekoratorlardan foydalanadi, bu ilova holatini boshqarish va unga reaksiyani soddalashtiradi.
Ushbu freymvorklar va kutubxonalar dekoratorlarning kod tashkilotini qanday yaxshilashini, umumiy vazifalarni soddalashtirishini va haqiqiy dunyo ilovalarida qo'llab-quvvatlanuvchanlikni qanday oshirishini ko'rsatadi.
Qiyinchiliklar va E'tiborga Olinadigan Jihatlar
- O'rganish Jarayoni: Dekoratorlar ishlab chiqishni soddalashtirishi mumkin bo'lsa-da, ularni o'rganish qiyin. Ular qanday ishlashini va ulardan samarali foydalanishni tushunish vaqt talab etadi.
- Nosozliklarni Tuzatish (Debugging): Dekoratorlarni disk raskadrovka qilish ba'zan qiyin bo'lishi mumkin, chunki ular dizayn vaqtida kodni o'zgartiradi. Kodingizni samarali disk raskadrovka qilish uchun to'xtash nuqtalarini qaerga qo'yish kerakligini tushunganingizga ishonch hosil qiling.
- Versiya Mosligi: Dekoratorlar TypeScript xususiyatidir. Har doim dekoratorlarning ishlatilayotgan TypeScript versiyasi bilan mosligini tekshiring.
- Haddan Tashqari Foydalanish: Dekoratorlardan haddan tashqari foydalanish kodni tushunishni qiyinlashtirishi mumkin. Ulardan oqilona foydalaning va ularning afzalliklarini ortib borayotgan murakkablik potentsiali bilan muvozanatlashtiring. Agar oddiy funksiya yoki yordamchi vosita ishni bajara olsa, shuni tanlang.
- Dizayn Vaqti va Ishga Tushirish Vaqti (Runtime): Unutmangki, dekoratorlar dizayn vaqtida (kod kompilyatsiya qilinganda) ishlaydi, shuning uchun ular odatda ishga tushirish vaqtida bajarilishi kerak bo'lgan mantiq uchun ishlatilmaydi.
- Kompilyator Natijasi: Kompilyator natijasidan xabardor bo'ling. TypeScript kompilyatori dekoratorlarni ekvivalent JavaScript kodiga transpilyatsiya qiladi. Dekoratorlarning qanday ishlashini chuqurroq tushunish uchun yaratilgan JavaScript kodini o'rganing.
Xulosa
TypeScript dekoratorlari kodingizning tuzilishini, qayta ishlatilishini va qo'llab-quvvatlanishini sezilarli darajada yaxshilaydigan kuchli metadasturlash xususiyatidir. Turli xil dekorator turlarini, ular qanday ishlashini va ulardan foydalanishning eng yaxshi amaliyotlarini tushunib, siz ulardan toza, ifodali va samaraliroq ilovalar yaratish uchun foydalanishingiz mumkin. Siz oddiy ilova yoki murakkab korporativ darajadagi tizim qurasizmi, dekoratorlar ishlab chiqish jarayonini yaxshilash uchun qimmatli vositani taqdim etadi. Dekoratorlarni qabul qilish kod sifatini sezilarli darajada yaxshilashga imkon beradi. Angular va NestJS kabi mashhur freymvorklar ichida dekoratorlar qanday integratsiyalashganini tushunib, dasturchilar kengaytiriladigan, qo'llab-quvvatlanadigan va mustahkam ilovalar yaratish uchun ularning to'liq salohiyatidan foydalanishlari mumkin. Asosiy narsa ularning maqsadini va ularni tegishli kontekstlarda qanday qo'llashni tushunish, afzalliklar har qanday potentsial kamchiliklardan ustun bo'lishini ta'minlashdir.
Dekoratorlarni samarali qo'llash orqali siz kodingizni yanada yaxshi tuzilish, qo'llab-quvvatlanuvchanlik va samaradorlik bilan yaxshilashingiz mumkin. Ushbu qo'llanma TypeScript dekoratorlaridan qanday foydalanish haqida keng qamrovli ma'lumot beradi. Ushbu bilim bilan siz yaxshiroq va qo'llab-quvvatlanadigan TypeScript kodi yaratish imkoniyatiga egasiz. Oldinga boring va bezang!