Skip to content

การทำงานของ TypeScript

TypeScript ทำงานโดยเป็นเหมือน "ตัวเสริม" ให้กับ JavaScript ที่ช่วยในเรื่อง type safety โดยมีขั้นตอนการทำงานในรายละเอียดดังนี้

1. ขั้นตอนการพัฒนา (Development Time)

เมื่อคุณเขียนโค้ด TypeScript:

  • การตรวจสอบแบบ Static Type: TypeScript จะตรวจสอบ type ทันทีขณะเขียนโค้ด ช่วยให้เห็นข้อผิดพลาดก่อนที่โค้ดจะถูกรัน เช่น หากคุณพยายามใช้เมธอดที่ไม่มีอยู่ในออบเจ็กต์ หรือส่งพารามิเตอร์ผิดประเภทให้กับฟังก์ชัน
  • IDE สามารถให้คำแนะนำ: เนื่องจากมีข้อมูล type จึงทำให้ IDE เช่น VS Code สามารถให้คำแนะนำ (autocomplete) ที่เหมาะสม แสดงเฉพาะเมธอดและพร็อพเพอร์ตี้ที่มีอยู่จริงในออบเจ็กต์นั้นๆ ทำให้เขียนโค้ดได้เร็วขึ้นและลดข้อผิดพลาด
  • ช่วยในการ Refactor: การเปลี่ยนแปลงโค้ดทำได้ปลอดภัยขึ้นเพราะ TypeScript จะแจ้งเตือนเมื่อมีการเปลี่ยนแปลงที่อาจก่อให้เกิดข้อผิดพลาด เช่น การเปลี่ยนชื่อฟังก์ชัน หรือเปลี่ยนโครงสร้างอินเตอร์เฟซ จะมีการแจ้งเตือนทุกจุดที่ต้องแก้ไขตาม
  • การตรวจสอบความสมบูรณ์: TypeScript ช่วยตรวจสอบว่าคุณได้จัดการกับทุกกรณีที่เป็นไปได้หรือไม่ เช่น เมื่อใช้ union types หรือ enum ทำให้ไม่พลาดการจัดการกับบางกรณี

2. การคอมไพล์ (Compilation Time)

เมื่อคุณคอมไพล์โค้ด TypeScript:

  • การตรวจสอบ Type อีกครั้ง: TypeScript Compiler (tsc) ตรวจสอบความถูกต้องของ type ทั้งหมดทั่วทั้งโปรเจ็กต์ ตรวจสอบความสอดคล้องระหว่างไฟล์ต่างๆ และแจ้งเตือนหากมีข้อผิดพลาด
  • การแปลงโค้ด (Type Erasure): TypeScript ถูกแปลงเป็น JavaScript ล้วนๆ โดยลบข้อมูล type ทั้งหมดออก เช่น type annotations, interfaces, generics จะถูกลบออกทั้งหมด เหลือเพียงโครงสร้างโค้ดที่ทำงานได้
  • การ Downlevel: คุณสามารถเลือกว่าต้องการให้ JavaScript ที่ได้เป็นเวอร์ชันใด (ES5, ES6, ES2020 ฯลฯ) ตามความต้องการ โดยกำหนดผ่าน target ใน tsconfig.json ช่วยให้โค้ดทำงานได้บนเบราว์เซอร์เก่าหรือสภาพแวดล้อมที่จำกัด
  • การแปลง Syntax ขั้นสูง: ฟีเจอร์ขั้นสูงของ TypeScript เช่น decorators, optional chaining, nullish coalescing จะถูกแปลงเป็นโค้ด JavaScript ที่ทำงานเทียบเท่ากัน

ตัวอย่างการแปลงโค้ด:

ts
// โค้ด TypeScript
interface Person {
    
name
: string;
age
: number;
} function
greet
(
person
: Person): string {
return `Hello, ${
person
.
name
}! You are ${
person
.
age
} years old.`;
} const
user
: Person = {
name
: "John",
age
: 30
};
console
.
log
(
greet
(
user
));

จะถูกแปลงเป็น:

js
// โค้ด JavaScript หลังการ transpile
function greet(person) {
    return "Hello, " + person.name + "! You are " + person.age + " years old.";
}

const user = {
    name: "John",
    age: 30
};

console.log(greet(user));

สังเกตว่า interface และ type annotations ทั้งหมดหายไป เหลือเพียงโค้ดที่ทำงานได้จริง

3. ในช่วงรันไทม์ (Runtime)

  • TypeScript หายไปหมด: ในช่วงรันไทม์ไม่มี TypeScript เหลืออยู่เลย เพราะเบราว์เซอร์และ Node.js รัน JavaScript เท่านั้น ทำให้ไม่มีโอเวอร์เฮดจากการตรวจสอบ type
  • ไม่มีการตรวจสอบ Type: การตรวจสอบ type ทั้งหมดทำเสร็จสิ้นแล้วในขั้นตอนก่อนหน้า ดังนั้นในรันไทม์จึงไม่มีการตรวจสอบ type อีก หากมีข้อผิดพลาดที่ไม่ถูกตรวจพบในช่วงคอมไพล์ ก็จะเกิดขึ้นในรันไทม์เหมือน JavaScript ทั่วไป
  • ประสิทธิภาพเทียบเท่า JavaScript: เนื่องจากโค้ดที่รันเป็น JavaScript ล้วนๆ จึงมีประสิทธิภาพเทียบเท่ากับการเขียน JavaScript โดยตรง ไม่มีการเสียประสิทธิภาพจากการตรวจสอบ type

4. เครื่องมือและการทำงานเพิ่มเติม

  • tsconfig.json: ไฟล์นี้ใช้กำหนดการตั้งค่าการคอมไพล์ เช่น:

    • target: กำหนดเวอร์ชัน JavaScript ที่ต้องการเป็นผลลัพธ์
    • module: กำหนดระบบโมดูลที่ใช้ (CommonJS, ESM, AMD)
    • strict: เปิดการตรวจสอบ type แบบเข้มงวด
    • lib: กำหนดไลบรารีมาตรฐานที่ต้องการใช้
    • outDir: กำหนดโฟลเดอร์สำหรับไฟล์ JavaScript ที่คอมไพล์แล้ว
  • ไฟล์ Declaration (.d.ts): ไฟล์เหล่านี้อธิบาย type ของโค้ด JavaScript เพื่อให้ TypeScript เข้าใจได้ โดยไม่มีโค้ดการทำงานจริง เป็นเพียงการประกาศ type เท่านั้น ช่วยให้สามารถใช้ไลบรารี JavaScript กับ TypeScript ได้

  • Type Definition (@types): ไลบรารี JavaScript มักมี type definition แยกต่างหาก เช่น @types/react ซึ่งสามารถติดตั้งผ่าน npm เพื่อให้ TypeScript เข้าใจไลบรารีนั้นๆ โดยไม่ต้องเขียน type definition เอง

  • Type Assertion: ในบางกรณีที่ TypeScript ไม่สามารถระบุ type ได้อย่างถูกต้อง คุณสามารถใช้ type assertion เพื่อบอก TypeScript ว่าตัวแปรมี type อะไร เช่น const elem = document.getElementById('app') as HTMLElement

  • Generics: เป็นเครื่องมือที่ทรงพลังใน TypeScript ที่ช่วยให้สามารถสร้างฟังก์ชันหรือคลาสที่ทำงานกับหลาย type ได้ แต่ยังคงรักษาความปลอดภัยของ type

5. ข้อดีของกระบวนการนี้

  • Zero Runtime Overhead: เนื่องจาก TypeScript ถูกแปลงเป็น JavaScript ล้วนๆ จึงไม่มี overhead ในช่วงรันไทม์ ไม่มีการเพิ่มขนาดไฟล์หรือลดประสิทธิภาพเมื่อเทียบกับ JavaScript โดยตรง
  • ความปลอดภัยในการพัฒนา: ได้ประโยชน์จากการตรวจสอบ type โดยไม่กระทบประสิทธิภาพเมื่อรันจริง ช่วยลดข้อผิดพลาดที่พบบ่อยใน JavaScript เช่น undefined is not a function, cannot read property of undefined
  • ใช้ร่วมกับ JavaScript เดิมได้: สามารถนำ TypeScript ไปใช้ในโครงการ JavaScript เดิมได้ทีละส่วน โดยการเปลี่ยนนามสกุลไฟล์จาก .js เป็น .ts และค่อยๆ เพิ่ม type annotation ทีหลัง ไม่จำเป็นต้องแปลงทั้งโปรเจ็กต์ในครั้งเดียว
  • การทำงานร่วมกับทีม: ช่วยให้ทีมพัฒนาเข้าใจโค้ดได้ง่ายขึ้น เพราะมี type ที่ชัดเจน ทำให้ทำงานร่วมกันได้ดีขึ้น โดยเฉพาะในโปรเจ็กต์ขนาดใหญ่
  • การบำรุงรักษาโค้ดระยะยาว: ช่วยให้การแก้ไขและปรับปรุงโค้ดในอนาคตทำได้ง่ายขึ้น เพราะ TypeScript จะช่วยตรวจสอบว่าการเปลี่ยนแปลงไม่ทำให้โค้ดส่วนอื่นเสียหาย

โดยสรุป TypeScript ทำหน้าที่เป็น "คนตรวจสอบความปลอดภัย" ในช่วงพัฒนาและคอมไพล์ แต่เมื่อถึงเวลารันจริง มันจะกลายเป็น JavaScript ธรรมดาที่มีประสิทธิภาพเทียบเท่ากับการเขียน JavaScript โดยตรง แต่มีความปลอดภัยด้าน type มากกว่า ทำให้ได้ประโยชน์ทั้งสองทาง คือความปลอดภัยในการพัฒนาและประสิทธิภาพในการทำงานจริง