Skip to content

Instantly share code, notes, and snippets.

@eimg
Last active February 19, 2025 03:06
Show Gist options
  • Save eimg/df13f7eb41a86af726e2a293ecf47539 to your computer and use it in GitHub Desktop.
Save eimg/df13f7eb41a86af726e2a293ecf47539 to your computer and use it in GitHub Desktop.
TypeScript - လိုတိုရှင်း

TypeScript - လိုတိုရှင်း

JavaScript ဟာ Dynamic Type Language တစ်ခုပါ။ Data Type တွေကို Language က လိုသလို အလိုအလျှောက် ပြောင်းလဲအလုပ်လုပ်ပေးတဲ့အတွက် ရေးသားသူက Type ကိစ္စ သိပ်ခေါင်းစားနေစရာမလိုဘဲ ရေးစရာရှိတဲ့ကုဒ်တွေကို ခပ်မြန်မြန် ရေးသွားလို့ရပါတယ်။

let value;        // undefined
value = "Alice";  // string
value = 42;       // number
value = true;     // boolean

ပေးလိုက်တဲ့ တန်ဖိုးကိုကြည့်ပြီး Type ကို အလိုအလျှောက်ပြောင်းပြီး အလုပ်လုပ်ပေးသွားတာပါ။ ဒီထိ အဆင်ပြေပါတယ်။ ပြဿနာ မရှိပါဘူး။

1 + 1;      //  2    : number + number
1 + 'a';    // '1a'  : string + string

ဒီထိလည်း အဆင်ပြေပါသေးတယ်။ Type မတူတာတွေ တွဲရေးထားပေမယ့် သူ့ဘာသာ ကြည့်လုပ်သွားပါတယ်။ နမူနာအရ 1 + 'a' လို့ပြောလိုက်တဲ့အခါ number 1 ကို အဆင်ပြေအောင် အလိုအလျှောက် string ပြောင်းပြီး အလုပ်လုပ်သွားတဲ့အတွက် အဖြေ '1a' ကို ရလိုက်တာပါ။

'10' + 1;   // '101'   : string + string
'10' - 1;   //  9      : number - number

ပြဿနာစပါပြီ။ '10' + 1 မှာ number 1 ကို string အဖြစ်ပြောင်းပြီး အလုပ်လုပ်သွားပေမယ့် '10' - 1 ကျတော့ 1 ကို string မပြောင်းတော့ဘဲ၊ '10' ကို number ပြောင်းပြီး အလုပ်လုပ်သွားပါတယ်။

1 + [];   // '1'
1 + {};   // '1[object Object]'

number 1 ကို Array အလွတ်နဲ့ပေါင်းတော့ string '1' ကို ပြန်ရပါတယ်။ Object အလွတ်နဲ့ ပေါင်းတော့ '1[object Object]' ဖြစ်သွားပါတော့တယ်။ Array အလွတ်ကို string ပြောင်းတဲ့အခါ Empty string ကို ရပြီး Object အလွတ်ကို string ပြောင်းတဲ့အခါ '[object Object]' ဆိုတဲ့ string ကို ရပါတယ်။

ဒီလိုကိစ္စတွေက ကုဒ်နည်းချိန်မှာ မသိသာပါဘူး။ များလာတဲ့အခါမှ ဒုက္ခပေးကြတာပါ။

သူ ဘယ်လိုပြောင်းပြီး ဘယ်လိုအလုပ်သွားမလဲဆိုတာ ကိုယ်မသိလိုက်တာတွေ ရှိနိုင်ပါတယ်။ ရုတ်တရက်ကြည့်လိုက်တော့ Error တွေမရှိဘူး၊ အလုပ်လုပ်နေတယ်လို့ ထင်ရပေမယ့်၊ မထင်မှတ်တဲ့အချိန် မထင်မှတ်တဲ့နေရာကျတော့မှ ထပြီးတော့ ဒုက္ခပေးပါလိမ့်မယ်။

ဒီလိုနဲ့ ကုဒ်တွေများလာတာနဲ့အမျှ အမှားတွေရှာရတာလည်း ပိုပြီးတော့ ခက်သွားပါလိမ့်မယ်။ အမှားပြနေတာက တစ်နေရာ၊ တကယ်မှားနေတာက အရင်ကတည်းက ကိုယ်မသိလိုက်ဘဲ မှားနေခဲ့တဲ့ တခြားနေရာ ဖြစ်နေပါလိမ့်မယ်။

ဒီပြဿနာကို ဖြေရှင်းဖို့ TypeScript ကို တီထွင် အသုံးပြုကြပါတယ်။ ကုဒ်တွေ ရေးတဲ့အခါ Type တွေကို ရေးသားသူက ကိုယ်တိုင်စီမံပြီး ရေးသားလို့ ရသွားသလို...

Type ကြောင့်ဖြစ်တဲ့ ပြဿနာတွေရှိခဲ့ရင် စောစောစီးစီး Compile Time မှာကတည်းက သိရှိဖြေရှင်းနိုင်မှာ ဖြစ်လို့ မထင်မှတ်တဲ့ အချိန်ကျမှ ထဒုက္ခပေးတဲ့ Runtime Error တွေ နည်းသွားမှာပဲ ဖြစ်ပါတယ်။

JavaScript တတ်ကျွမ်းပြီးသားသူအတွက် TypeScript ကို ပြောင်းလဲအသုံးပြုရတာ သိပ်မခက်လှပါဘူး။ ဒါပေမယ့် ကိုယ်တိုင်အပါအဝင် အကြောင်းအမျိုးမျိုးနဲ့ ပီပီပြင်ပြင် ပြောင်းမသုံးဖြစ်သူတွေ အများကြီး ရှိနေကြပါတယ်။

အလေ့အကျင့်ဖြစ်နေတော့ တခါတရံ စိတ်ညစ်ရပေမယ့် ဒီအတိုင်းလည်း JavaScript နဲ့ အဆင်ပြေနေတာကြောင့် ပါသလို၊ ပြောင်းဖို့စမ်းကြည့်လိုက် ကုဒ်တွေပိုရှုပ်သွားတယ်လို့ ခံစားရလို့ ရပ်ထားလိုက်၊ ပြောင်းဖို့စမ်းကြည့်လိုက် လွယ်လွယ်လေးနဲ့ ပြီးရမှာကို ပိုခက်သွားတယ်ထင်လို့ ရပ်ထားလိုက်နဲ့ သေချာကို မလုပ်ဖြစ်တော့ဘူး ဖြစ်နေကြသူတွေ ရှိပါလိမ့်မယ်။

အဲ့ဒီလို ဖြစ်နေသူအတွက် တစ်နေရာထဲမှာ၊ တစ်ထိုင်ထဲ လေ့လာကြည့်လိုက်ယုံနဲ့၊ TypeScript ကို တခါထဲ သေသေချာချာ ရသွားစေဖို့ ရည်ရွယ်ပြီး ဒီသင်ခန်းစာကို ရေးသားပါတယ်။ ဖတ်ရှုသူက JavaScript တတ်ကျွမ်းထားပြီး ဖြစ်ဖို့လိုပါတယ်။ လိုအပ်ရင် JavaScript - လိုတိုရှင်း စာအုပ်မှာ JavaScript ကို အခြေခံကနေစပြီး လေ့လာနိုင်ပါတယ်။

Type Inference

TypeScript နဲ့ ကုဒ်တွေရေးသားတဲ့အခါ ရေးသားသူက Type ကို ကိုယ်တိုင်စီမံရေးသားလို့ ရတယ်ဆိုပေမယ့် အမြဲတမ်း ကိုယ်တိုင်လုပ်နေစရာတော့ မလိုအပ်ပါဘူး။ TypeScript က သင့်တော်တဲ့ Type ကို အလိုအလျှောက် အသုံးပြုအလုပ်လုပ်ပေးနိုင်ပါတယ်။

let value = 42;   // value -> number

Type ကို မပြောပေမယ့် ထည့်သွင်းလိုက်တဲ့ တန်ဖိုးကိုကြည့်ပြီး သူ့ဘာသာ သတ်မှတ်အသုံးပြု အလုပ်လုပ်ပေးသွားမှာပါ။ ဒီလိုသဘောသဘာဝ ရှိတဲ့အတွက် ကုဒ်တွေရေးတဲ့အခါ TypeScript ရယ်လို့ သီးခြားရေးနည်းတွေ မလိုသေးဘဲ JavaScript နဲ့ ရေးသားသကဲ့သို့ပဲ ဆက်လက်ရေးသားနိုင်မှာ ဖြစ်ပါတယ်။

let value = 42;   // value -> number
value = "Alice";  // Error: not assignable

အပြောင်းအလဲက စပါပြီ။ ရိုးရိုး JavaScript သာဆိုရင် value ကို အလျှောက် string အဖြစ်ပြောင်းပြီး ပေးလိုက်တဲ့ တန်ဖိုးသစ်ကို လက်ခံသွားမှာပါ။ TypeScript ကတော့ လက်မခံပါဘူး။ value ဟာ number Data Type ဖြစ်တဲ့အတွက် string ကို Assign လုပ်တာ လက်မခံကြောင်း Error ပေးပါလိမ့်မယ်။

let value: number = 42;
let hello: string = "Hello World";

နမူနာအရ value ကို စတင်ကြေညာစဉ်ကတည်းက number အဖြစ် ကြေညာထားတာကို တွေ့ရမှာဖြစ်သလို hello ကိုတော့ string အဖြစ်ကြေညာထားတာကို တွေ့ရမှာဖြစ်ပါတယ်။ ဒီနည်းနဲ့ ကိုယ့်ဘာသာ Type ကို ကြေညာသတ်မှတ်ပေးမယ်ဆိုရင်လည်း ရနိုင်ပါတယ်။

function add(a: number, b: number) {
  return a + b;
}

နမူနာအရ Function add() က a နဲ့ b ကို လက်ခံထားပါတယ်။ Return Type တော့ သတ်မှတ်မထားပါဘူး။ TypeScript က number ကို Return ပြန်ပေးထားကြောင်း အလိုအလျှောက်သိပြီး Return Type အဖြစ် number ကိုပဲ အသုံးပြုအလုပ်လုပ်ပေးသွားမှာပါ။

function add(a: number, b: number): number {
  return a + b;
}

ဒီတစ်ခါတော့ Return Type ကိုပါ ကိုယ့်ဘာသာ number လို့ သတ်မှတ်ပေးလိုက်ပါပြီ။

let nums = [1, 2, 3];
nums.map(n => n + 1);

နမူနာမှာ n ရဲ့ Type ကို number အဖြစ် TypeScript က အလိုအလျှောက် သိရှိအလုပ်လုပ်သွားပါလိမ့်မယ်။ ဘာကြောင့်လည်းဆိုတော့ စတင်သတ်မှတ်ထားတဲ့ nums[] က number Array ဖြစ်နေတဲ့အတွက် အထဲက တန်ဖိုးတွေဟာ number ဖြစ်ကြောင်း သိပြီးဖြစ်လို့ပါ။

const user = { name: "Alice", age: 25 };
const { name, age } = user;

နမူနာမှာ name က string ဖြစ်ပြီး age က number ဖြစ်ပါလိမ့်မယ်။ ဒီလိုကိစ္စမျိုးထိ TypeScript က အလိုအလျှောက် သိရှိအလုပ်လုပ်ပေးနိုင်ပါတယ်။ ဒါဟာ TypeScript နဲ့ပက်သက်ရင် ပထမဆုံး သတိပြုရမယ့်အချက်ပါ။ Type ကို Explicit Type အနေနဲ့ ကိုယ်တိုင်သတ်မှတ်ပေးလို့ရသလို Type Inference သဘောသဘာဝနဲ့ အလိုအလျှောက် သတ်မှတ် အလုပ်လုပ်သွားတာတွေလည်း ရှိပါလိမ့်မယ်။

တိကျတဲ့ Type ပေါ်မှာအခြေခံပြီး အလုပ်လုပ်ပေမယ့် နေရာတကာ Type တွေကို ကိုယ်ကလိုက်သတ်မှတ်ပေးနေစရာ မလိုဘူးဆိုတဲ့ သဘောပါပဲ။

ဒီကုဒ်တွေနဲ့ ဆက်လက်ဖော်ပြမယ့် ကုဒ်တွေကို TypeScript Playground မှာ လိုက်ပြီးတော့ ရေးသားစမ်းသပ်ကြည့်နိုင်ပါတယ်။

Defining Types

Type တွေ ကိုယ့်ဘာသာ ကြေညာသတ်မှတ် အသုံးပြုပုံကို အထက်မှာ နမူနာတချို့ တွေ့ခဲ့ပြီးပါပြီ။ ဖြည့်စွက်မှတ်သားသင့်တာက Object Type နဲ့ Union Type တို့အကြောင်းပဲ ဖြစ်ပါတယ်။

const user: {name: string; age: number} = {
  name: "Alice",
  age: 22,
};

user Object ကို ကြေညာစဉ်မှာ name ဟာ string ဖြစ်ပြီး age ဟာ number ဖြစ်ကြောင်း ကြေညာပေးလိုက်တာပါ။ ဒီလိုရိုးရှင်းတဲ့ Object မျိုးမှာ ကိုယ်တိုင်ကြေညာပေးနေစရာတော့ မလိုပါဘူး။ Type Inference သဘောသဘာဝနဲ့ သူ့ဘာသာ သိနိုင်ပါတယ်။ ဒါပေမယ့် ကြေညာပေးဖို့ လိုတဲ့နေရာတွေ ရှိလာမှာဖြစ်ပါတယ်။ ဒါကြောင့် ဘယ်လိုကြေညာ အသုံးပြုရသလဲဆိုတာကို သိဖို့လိုသွားတာပါ။

နမူနာမှာ Inline Type ရေးနည်းကိုအသုံးပြုထားပါတယ်။ အဲ့ဒီလို Inline မဟုတ်ဘဲ ကြိုတင်သတ်မှတ်ပေးလို့လည်းရပါတယ်။

interface User {
  name: string;
  age: number;
}

const user: User = {
  name: "Alice",
  age: 25,
};
type User = {
  name: string;
  age: number;
};

const user: User = {
  name: "Alice",
  age: 25,
};

interface ကို အသုံးပြုနိုင်သလို၊ type ကိုလည်း အသုံးပြုပြီး ကြိုတင်ကြေညာလို့ရတာပါ။ ရေးနည်းအနည်းငယ် ကွဲပြားတာကို သတိပြုပါ။ ဒီနှစ်ခုကြားထဲမှာ ကွဲပြားမှုတွေရှိပေမယ့် ထည့်မပြောချင်သေးပါဘူး။ နောက်မှ အသေးစိတ် ဆက်လက်လေ့လာကြည့်ပါ။ ဒီနေရာမှာတော့ ရေးနည်းအနေနဲ့ အခုလို နှစ်မျိုးရေးလို့ရတယ်လို့ပဲ အတိုချုပ် မှတ်ထားစေချင်ပါတယ်။

let id: number | string;
id = 123;
id = "abc";

ဒါကတော့ Union Type ဖြစ်ပါတယ်။ Type တစ်မျိုးထက်ပိုပြီး လက်ခံအလုပ်လုပ်လိုတဲ့အခါ အသုံးဝင်ပါတယ်။ ဥပမာ - URL Query Parameter တွေမှာ id ကို string ဆိုရင်လည်း လက်ခံအလုပ်လုပ်မယ်၊ number ဆိုရင်လည်း လက်ခံအလုပ်လုပ်မယ် ဆိုတာမျိုးက လိုအပ်တတ်ပါတယ်။

နည်းနည်းပိုကျယ်ပြန့်တဲ့ ဥပမာလေး ပေးကြည့်ပါမယ်။

type Success = {
  msg: string;
  color: 'green' | 'white';
}

type Warning = {
  msg: string;
  color: 'yellow' | 'white';
}

function show(variant: Success | Warning) {
  //
}

နမူနာအရ Type က Success ဆိုရင် color အဖြစ် 'green' သို့မဟုတ် 'white' ကို အတိအကျ လက်ခံလို့ရသွားပါတယ်။ show() Function က variant ကို Argument အဖြစ် လက်ခံပြီး အဲ့ဒီ variant က Success သို့မဟုတ် Warning Type တွေ ဖြစ်လို့ရသွားပါတယ်။ ဒီလို နည်းလမ်းမျိုးတွေနဲ့ အသုံးဝင်တဲ့ ရေးနည်းပဲ ဖြစ်ပါတယ်။

Object Type တွေ ကြေညာတဲ့အခါ Optional Property တွေကိုလည်း ထည့်သွင်းကြေညာလို့ရပါတယ်။

interface Person {
  name: string;
  age?: number;
}

type User = {
  name: string;
  age?: number;
}

const alice: Person = { name: "Alice" };
const bob: Person = { name: "Bob", age: 22 };

နမူနာအရ Person Interface မှာရော User Type မှာပါ age က Optional ဖြစ်သွားပါတယ်။ ဒါကြောင့် ဒီ Interface တွေ Type တွေကို အသုံးပြုတဲ့အခါ name ကို မဖြစ်မနေပေးဖို့လိုပေမယ့် age ကတော့ လိုအပ်ရင်ပေးနိုင်တယ်၊ မပေးဘဲ ထားလို့လည်း ရသွားပါတယ်။ ? သင်္ကေတလေး ထည့်ရေးထားလို့ပါ။

Generics

TypeScript မှာ Generic ရေးနည်းနဲ့ ပုံစံပြောင်းပြီး ပြန်လည်အသုံးပြုလို့ရတဲ့ လုပ်ဆောင်ချက်တွေကို ရရှိနိုင်ပါတယ်။

function wrap<T>(value: T): T[] {
  return [value];
}

နမူနာအရ wrap() Function က value ကို လက်ခံပြီး Array ကို ပြန်ပေးပါတယ်။ ထူးခြားသွားတာက Angle Bracket နဲ့ ရေးထားတဲ့ <T> ပါသွားလို့ wrap() ဟာ ရိုးရိုး Function မဟုတ်တော့ဘဲ Generic Function ဖြစ်သွားပါတယ်။ Generic Function မှာ Type ကို ပုံသေကြိုတင် သတ်မှတ်ထားတာ မဟုတ်တော့ဘဲ အသုံးပြုတဲ့အခါမှ ပေးလို့ရသွားမှာပါ။ နမူနာအရ ပေးလာတဲ့ Argument Type နဲ့ ပြန်ရမယ့် Array ရဲ့ Type တူသွားမှာ ဖြစ်ပါတယ်။

const hello = wrap('hello');  // string[]
const num = wrap(123);        // number[]

wrap() ကို ခေါ်စဉ်မှာ string ကိုပေးလိုက်ရင် string Array ကိုပြန်ရမှာဖြစ်ပြီး number ကို ပေးလိုက်ရင် number Array ကို ပြန်ရမှာ ဖြစ်ပါတယ်။ နည်းနည်းပိုလက်တွေ့ကျတဲ့ ဥပမာလေး ပေးကြည့်ပါမယ်။

type Res<T> = {
  data: T;
  status: number;
}

type User = {
  name: string;
  age: number;
}

type Post = {
  title: string;
  body: string;
}

const user: Res<User> = {
  data: { name: 'Alice', age: 22 },
  status: 200,
};

const post: Res<Post> = {
  data: { title: 'Some title', body: '…' },
  status: 200,
};

နမူနာအရ Res ဟာ data နဲ့ status ဆိုတဲ့ Property နှစ်ခုပါဝင်တဲ့ Generic Type ဖြစ်သွားပါတယ်။ status က number ဖြစ်ရပါမယ်။ ဒါပေမယ့် data ကတော့ ကြိုတင်သတ်မှတ် မထားပါဘူး။ အသုံးပြုစဉ်မှာ ပေးတဲ့ Type ကို အသုံးပြုသွားမှာပဲ ဖြစ်ပါတယ်။ နမူနာအရ Res ကို အသုံးပြုစဉ်မှာ User ကို Type အနေနဲ့ပေးလိုက်တဲ့အတွက် data ရဲ့ Type ဟာ User ဖြစ်သွားမှာပဲ ဖြစ်ပါတယ်။

ဒီ Generic ရေးနည်းဟာ JavaScript သမားတွေအတွက် TypeScript မှာ မျက်စိလည်စရာ အကောင်းဆုံးကိစ္စ ဖြစ်နိုင်ပါတယ်။ ဒါကိုနားလည်ရင် TypeScript က ရသွားပါပြီ။ ကျန်တာတွေက ဒီလောက်ကြီး နားလည်ရ မခက်လှသလို အသုံးပြုရလည်း မခက်လှပါဘူး။

နမူနာအရ user.data.name ဟာ Valid ဖြစ်ပေမယ့် user.data.title ကတော့ Valid မဖြစ်တာကို TypeScript က သိသွားပါပြီ။ VS Code လို Editor မျိုးကလည်း သိသွားပါပြီ။ ဒါကြောင့် ဒီရေးနည်းကို ကျွမ်းကျင်ရင် ကိုယ့်ရဲ့ကုဒ်က ပိုပြီးတော့ စနစ်ကျသွားယုံသာမက၊ ဒီကုဒ်ကို အသုံးပြု အလုပ်လုပ်ရတဲ့ Developer Experience ကလည်း အများကြီးပိုပြီးတော့ ကောင်းသွားမှာပဲ ဖြစ်ပါတယ်။

TypeScript in React

React ပရောဂျက်တွေမှာ TypeScript နဲ့ Component props တွေ state တွေရဲ့ Type တွေကို စီမံရေးသားလို့ရပါတယ်။

type UserProps = {
  name: string;
  age: number;
}

export default function User({ name, age }: UserProps) {
  //
}

နမူနာအရ <User> Component ရဲ့ name နဲ့ age props တွေအတွက် ကြိုတင်ကြေညာထားတဲ့ UserProps Type ကို အသုံးပြုလိုက်တာပါ။ ဒီလိုမျိုး React TypeScript နမူနာကုဒ်တွေကို တစ်ခါထဲ လိုက်ရေးကြည့်ချင်ရင် playcode.io မှာ ရေးသားကြည့်နိုင်ပါတယ်။

မူကွဲအနေနဲ့ မှတ်သားသင့်တဲ့ ရေးနည်းလည်း ရှိပါသေးတယ်။

import React from "react";

type UserProps = {
  name: string;
  age: number;
}

const User: React.FC<UserProps> = ({ name, age }) => {
  //
}

export default User;

ဒီနမူနာမှာ props အတွက် Type ကို တိုက်ရိုက်မရေးဘဲ React.FC (Function Component) ကနေတစ်ဆင့် ရေးသားအသုံးပြုထားပါတယ်။ React.FC က Return Type ကို null သို့မဟုတ် JSX Element ဖြစ်ကြောင်း ကြိုတင်သတ်မှတ်ထားပေးပါတယ်။ ဒါပေမယ့် မဖြစ်မနေတော့ မလိုအပ်ပါဘူး။ Type Inference သဘောသဘာဝကြောင့် Return Type ကို မပြောလည်း TypeScript က အလိုအလျှောက် သင့်တော်အောင် ပြန်ပေးနိုင်ပါတယ်။

import { useState } from 'react';

type UserModel = {
  name: string;
  age: number;
};

export default function User() {
  const [user, setUser] = useState<UserModel | null>(null);
  //
}

ဒီတစ်ခါတော့ user State အတွက် Type ကို UserModel သို့မဟုတ် null အဖြစ် သတ်မှတ်ပေးလိုက်တာပါ။

တခြား ref တို့ event တို့လို လုပ်ဆောင်ချက်တွေ အတွက်လည်း Type တွေ ရေးသားစီမံလို့ ရနိုင်ပါတယ်။ ဒါပေမယ့် Type Inference ကြောင့် အမြဲတမ်း ကိုယ်တိုင်စီမံစရာ မလိုတဲ့အတွက် နမူနာ ထည့်မပေးတော့ပါဘူး။

Context တွေအတွက် Type တွေ စီမံလိုရင်လည်း ရပါတယ်။ စောစောက State အတွက် ရေးပုံရေးနည်းနဲ့ သိပ်မကွာပါဘူး။

import { useState, createContext } from 'react';

type AuthContextType = {
  auth: { name: string } | null;
  login: () => void;
}

const AuthContext = createContext<AuthContextType | undefined>(undefined);

export default function App() {
  const [auth, setAuth] = useState<{ name: string } | null>();

  const login = () => {
    setAuth({ name: "Alice" });
  }

  return <AuthContext.Provider value={{ auth, login }}>
    {/**/}
  </AuthContext.Provider>
}

AuthContext ရဲ့ ရှိရမယ့်ဖွဲ့စည်းပုံကို AuthContextType အဖြစ် ကြိုတင်သတ်မှတ်လိုက်ပြီး createContext() နဲ့ Context ကို တည်ဆောက်စဉ်မှာ အသုံးပြုလိုက်တာပါ။

TypeScript in Express

TypeScript ကို Express ပရောဂျက်တွေမှာလည်း အသုံးပြုနိုင်ပါတယ်။ အခြေခံရေးနည်းတချို့ ထည့်ပြောချင်ပါတယ်။

import { Request, Response } from 'express';

interface NewUserRequest extends Request {
  body: {
    name: string;
    age: number;
  };
}

app.post('/user', (req: NewUserRequest, res: Response) => {
  const { name, age } = req.body;

  //
});

နမူနာအရ NewUserRequest က Express Request ကို extends လုပ်ထားပါတယ်။ ဒါကြောင့် TypeScript က req Object ရဲ့ body မှာပါလာမယ့် ဖွဲ့စည်းပုံ အကြောင်းကို တိတိကျကျသိရှိစီမံနိုင်သွားမှာပဲ ဖြစ်ပါတယ်။ ဒီနည်းပေါ်မှာ အခြေခံပြီး req.params တို့ req.query တို့အတွက်လည်း အလားတူ စီမံရေးသားနိုင်မှာပဲ ဖြစ်ပါတယ်။

Express နဲ့ ပရောဂျက်တချို့ လုပ်ဖူးရင် res.locals လို့ခေါ်တဲ့ အသုံးဝင်တဲ့ လုပ်ဆောင်ချက်အကြောင်းကို သိပါလိမ့်မယ်။ Middleware တွေ Route တွေအကြား Share လုပ်ဖို့ လိုတဲ့ Data တွေရှိရင် သူ့ကိုသုံးရတာပါ။ res.locals ကို Generic သုံးပြီးတော့ အခုလို စီမံရေးသားနိုင်ပါတယ်။

import { Request, Response, NextFunction } from 'express';

interface Locals<T = {}> {
  locals: T;
}

app.get('/profile', auth, (
  req: Request,
  res: Response & Locals<{
    user: { name: string; email: string }
  }>
) => {
  res.json({ /* profile data */ });
});

ကုဒ်အပြည့်အစုံမဟုတ်ပါဘူး။ သဘောသဘာဝကိုပဲ ချရေးထားတာပါ။ နမူနာအရ res.locals မှာ ခဏထည့်သိမ်းချင်တဲ့ Data တွေရှိတဲ့အခါ Locals Type ကို အသုံးပြုလိုက်မှာပါ။ နမူနာမှာ res အတွက် Type အဖြစ် Express Response နဲ့ Locals ကို & သင်္ကေတနဲ့ နှစ်ခုတွဲ သုံးပြထားတာကို သတိပြုပါ။ အဲ့ဒီလိုလည်း သုံးလို့ရပါတယ်။

TypeScript in fetch()

နောက်ဆုံးအပိုင်းအနေနဲ့ fetch() အပါအဝင် Promise ကို အခြေခံတဲ့ ကုဒ်တွေကို TypeScript နဲ့ စီမံရေးသားပုံ အကြောင်းလည်း ထည့်ပြောချင်ပါတယ်။

type User = {
  id: number;
  name: string;
  email: string;
}

async function fetchAllUsers(): Promise<User[]> => {
  const res = await fetch(api);
  return await res.json();
};

Return Type ကို အဓိကကြည့်ရမှာပါ။ နမူနာအရ Return Type က Promise ဖြစ်ပြီး အဲ့ဒီ Promise Resolve ဖြစ်သွားရင် ရလာမှာက User Array ဖြစ်ကြောင်း သတ်မှတ်ပေးထားတာပါ။ ဒါကြောင့် TypeScript က Promise ဖြစ်ကြောင်း သိသွားယုံသာမက Resolve Data ရဲ့ ဖွဲ့စည်းပုံကိုပါ သိသွားမှာပဲ ဖြစ်ပါတယ်။

Conclusion

JavaScript Developer တစ်ဦးအတွက် TypeScript ဆိုတာ အချိန်အများကြီး ထပ်ပေးစရာမလိုဘဲ လေ့လာအသုံးပြုနိုင်တဲ့ နည်းပညာဖြစ်ပေမယ့် အကြောင်းအမျိုးမျိုးကြောင့် မလေ့လာဖြစ်၊ မသုံးဖြစ်ကြသူများအတွက် ဒီသင်ခန်းစာက အထောက်အကူ ဖြစ်လိမ့်မယ်လို့ ယူဆပါတယ်။

အဓိကကျတဲ့ အပိုင်းတွေကို လိုတိုရှင်း ရွေးထုတ်ဖော်ပြခဲ့တာဖြစ်လို့ ကျန်ရှိနေသေးတဲ့ အသေးစိတ်လေးတွေတော့ ရှိပါသေးတယ်။ ဥပမာ - any Type အကြောင်းဆိုရင် ထည့်ပြောမထားပါဘူး။ နောက်ပြီးတော့ React Query, React Router စတဲ့ နည်းပညာတွေ အပါအဝင် Library တစ်ခုချင်းအလိုက် သတိပြုသင့်တဲ့ ထူးခြားချက်လေးတွေလည်း ရှိကြပါသေးတယ်။ ဒီလို ဆက်လက်လေ့လာစရာတွေ ကျန်သေးပေမယ့် အခုဒီနေရာမှာ လေ့လာခဲ့သလောက် သိရှိသွားပြီဆိုရင် စတင်အသုံးပြုဖို့အတွက် အသင့်ဖြစ်သွားပြီလို့ ဆိုနိုင်ပါတယ်။

"TypeScript - လိုတိုရှင်း" အမည်နဲ့ စာအုပ်တစ်အုပ်အဖြစ် ဖန်တီးရင်ကောင်းမလားလို့ စဉ်းစားပါသေးတယ်။ JavaScript ရပြီးသားသူဆိုရင် စာအုပ်တစ်အုပ်စာတောင် အချိန်ပေးပြီးဖတ်နေဖို့ မလိုပါဘူး၊ ဒီလောက်ဆိုရင် အဆင်ပြေလောက်ပါပြီလို့ တွေးမိလို့ အခုလို ဆောင်းပါးတစ်ပုဒ်စာ သင်ခန်းစာတစ်ခုအနေနဲ့ပဲ ရေးသားဖြစ်လိုက်ပါတယ်။

အားလုံးပဲအဆင်ပြေကြပါစေ။

@kaungzawhein543
Copy link

Thank you sir

@Click777777
Copy link

Thank you pr Sayar

@HealerK
Copy link

HealerK commented Nov 27, 2024

Thank you very much pr Sayar

@mintechkyaw
Copy link

thank sir

@KyawKyawLin19
Copy link

thanks sir

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment