Skip to content
GitHub

Generic များကို ထိန်းချုပ်ခြင်း: ကန့်သတ်ချက်များ (Constraints)

အဓိက ပြဿနာ: Generic တွေက တစ်ခါတလေ ပိုပြီး လိုက်လျောလွန်းနေခြင်း

Section titled “အဓိက ပြဿနာ: Generic တွေက တစ်ခါတလေ ပိုပြီး လိုက်လျောလွန်းနေခြင်း”

Generic တွေက T က ဘာ Type မဆို ဖြစ်လို့ရတယ်ဆိုတဲ့အတွက် တကယ် အစွမ်းထက်ပါတယ်။ ဒါပေမယ့် တစ်ခါတလေကျတော့ အဲဒီ လိုက်လျောလွန်းတာကြီးကပဲ ပြဿနာ ပြန်ဖြစ်တတ်တယ်။ ဥပမာ - ကျွန်တော်တို့ရဲ့ Generic Function ထဲမှာ argument (လက်ခံရရှိတဲ့ Data) ရဲ့ Property တစ်ခုခုကို သုံးချင်တယ်ဆိုပါစို့။

ဥပမာအနေနဲ့၊ လက်ခံရရှိတဲ့ Data ရဲ့ Length ကို Console မှာ ထုတ်ပြမယ့် Function လေးတစ်ခု ရေးကြည့်ရအောင်။

index.ts
function logLength<T>(arg: T): void {
// TypeScript က Error ပြလိမ့်မယ်!
// console.log(arg.length); // ERROR: Property 'length' does not exist on type 'T'.
}

ဒီမှာ TypeScript က မှန်မှန်ကန်ကန်ပဲ Error ပြတယ်။ ဘာလို့လဲ? ဘာလို့လဲဆိုတော့ T က ဘယ် Type မဆို ဖြစ်နိုင်တယ်လေ။ တကယ်လို့ တစ်ယောက်ယောက်က logLength(123) လို့ ခေါ်လိုက်ရင် ဘာဖြစ်မလဲ? number Type တွေမှာ .length ဆိုတဲ့ Property မှ မရှိတာ။ ဒါမှမဟုတ် logLength({ name: 'Bob' }) လို့ ခေါ်ရင်ရော? အဲဒီ object မှာလည်း .length ဆိုတာ မရှိဘူး။ ဒီလိုမျိုး T က တကယ့်ကို ဘာမဆို ဖြစ်နိုင်နေရင် ကျွန်တော်တို့ရဲ့ Function က Type Safety မဖြစ်တော့ဘူး (စိတ်မချရတော့ဘူး)။

ဖြေရှင်းနည်း: extends ကို အသုံးပြု၍ ကန့်သတ်ခြင်း (Constraints)

Section titled “ဖြေရှင်းနည်း: extends ကို အသုံးပြု၍ ကန့်သတ်ခြင်း (Constraints)”

ဒီတော့ ကျွန်တော်တို့ TypeScript ကို ပြောပြဖို့ လိုလာပြီ။ ‘အိုကေ၊ T က Flexible ဖြစ်ပါစေ၊ ဒါပေမယ့် သူဟာ length ဆိုတဲ့ Property တစ်ခု ပါကို ပါရမယ် (ပြီးတော့ အဲဒီ Property က ဖြစ်နိုင်ရင် number Type ဖြစ်သင့်တယ်)’ လို့ သတ်မှတ်ပေးရမယ်။

ဒီလို သတ်မှတ်တာကို Generic ကြေညာတဲ့နေရာမှာ extends Keyword ကို အသုံးပြုပြီး လုပ်ပါတယ်။

index.ts
// ကျွန်တော်တို့ လိုအပ်တဲ့ Property ရှိကြောင်း ဖော်ပြမယ့် Interface လေးတစ်ခု အရင်သတ်မှတ်မယ်
interface Lengthwise {
length: number;
}
// T ကို ကန့်သတ်လိုက်မယ်: T ဟာ Lengthwise Interface မှာ ရှိတဲ့ Property တွေ ပါကို ပါရမယ်
function logLength<T extends Lengthwise>(arg: T): void {
// အခုဆိုရင် TypeScript က arg မှာ .length Property ရှိကြောင်း သိနေပြီ!
console.log(`Length: ${arg.length}`);
}

ကန့်သတ်ထားသော Generic များကို အသုံးပြုခြင်း

Section titled “ကန့်သတ်ထားသော Generic များကို အသုံးပြုခြင်း”

ဒီလို ကန့်သတ်ချက် ထည့်လိုက်တော့ ကျွန်တော်တို့ရဲ့ Function က ကန့်သတ်ချက်နဲ့ ကိုက်ညီတဲ့ Type တွေနဲ့ စိတ်ချစွာ အလုပ်လုပ်နိုင်သွားပြီ။

index.ts
logLength("Hello TypeScript!"); // အလုပ်လုပ်တယ် (string မှာ length ရှိတယ်)
logLength([1, 2, 3, 4]); // အလုပ်လုပ်တယ် (array မှာ length ရှိတယ်)
logLength({ length: 10, value: "Data" }); // အလုပ်လုပ်တယ် (ဒီ object မှာ length property ပါတယ်)
// logLength(123); // ERROR: number Type က Lengthwise Type နဲ့ မကိုက်ညီဘူးလို့ TypeScript က Error ပြပြီ။
// logLength({ name: "No length" }); // ERROR: length Property ပျောက်နေတယ်လို့ Error ပြပြီ။
// logLength({}); // ERROR: length Property ပျောက်နေတယ်လို့ Error ပြပြီ။

တစ်ခါတလေကျတော့ သီးခြား Interface တစ်ခု သတ်မှတ်ဖို့တောင် မလိုပါဘူး။ တခြား Type တစ်ခုရဲ့ ပုံစံ (shape) အတိုင်း တိုက်ရိုက် ကန့်သတ်လို့ရတယ်။ keyof T လိုမျိုး Keyword တွေကို သုံးတာပေါ့။ keyof T ဆိုတာက T Type မှာရှိတဲ့ Property တွေရဲ့ နာမည်တွေကို ပြောတာ။

index.ts
// T က မည်သည့် object type မဆို ဖြစ်ရမယ်၊ K ကတော့ T ရဲ့ Property နာမည်တွေထဲက တစ်ခု ဖြစ်ရမယ်လို့ သတ်မှတ်လိုက်တာ
function getProperty<T extends object, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key]; // obj ထဲက key ဆိုတဲ့ property ရဲ့ တန်ဖိုးကို ပြန်ထုတ်မယ်
}
let user = { name: "Alice", age: 30 }; // user က { name: string; age: number; } Type
// user object ထဲက "name" ဆိုတဲ့ property ကို ယူမယ်
let userName = getProperty(user, "name"); // Works! K က "name" ဖြစ်သွားတယ်၊ T က user ရဲ့ Type
console.log(userName); // Output: Alice
// user object ထဲက "address" ဆိုတဲ့ property ကို ယူကြည့်မယ်
// let userAddress = getProperty(user, "address"); // ERROR: "address" ဆိုတာ user ရဲ့ Property နာမည်တွေ ("name" | "age") ထဲမှာ မပါဘူးလို့ TypeScript က Error ပြပြီ။

ဒီလို သတ်မှတ်လိုက်တော့ getProperty Function ကို ခေါ်တဲ့အခါ obj ဆိုတဲ့ object ရယ်၊ အဲဒီ object ထဲမှာ တကယ်ရှိတဲ့ Property ရဲ့ နာမည် (key) ရယ် ပဲ လက်ခံတယ်။ မရှိတဲ့ Property နာမည်ကို ထည့်ခေါ်ရင် Code ရေးနေတုန်းမှာတင် TypeScript က Error ပြပေးတယ်။ ပြန်ထွက်လာမယ့် Data ရဲ့ Type ကလည်း T[K] (T ထဲက K ဆိုတဲ့ Property ရဲ့ Type) လို့ တိတိကျကျ သိရတယ်။