หากใครที่ใช้งาน typescript อยู่น่าจะเคยเห็นวิธีการประกาศ type อยู่ 2 รูปแบบหลักๆ คือ แบบ interface และแบบ type (Aliases Type) ซึ่งทั้ง 2 ตัวนี้อาจทำให้หลายคนสับสนได้ว่าเราจะใช้อะไรดี ซึ่งผมก็เป็นเหมือนกัน เลยถือโอกาศเขียนบนความไว้กันงง


ทำความรู้จักกันก่อน

เริ่มจากมาทำความรู้จักการประกาศ type ทั้ง 2 แบบก่อน

Interface

interface จะเป็นตัวกำหนดว่า Object หรือ Class นั้นๆ จะมีหน้าตาอย่างไรบ้าง ถ้าใครรู้จัก OOP อยู่แล้ว ก็น่าจะคุ้นชินกับชื่อนี้ มันทำหน้าที่คล้ายๆ กันเลย แต่อาจจะมีการทำงานบางอย่างที่แตกต่างกันบ้าง (อาจจะเก็บไว้เขียนใน blog ต่อๆ ไป)

โดยเราสามารถการประกาศ interface ได้ดังนี้:

interface Person {
  name: string;
  age: number;
  gender?: string;  // Optional property
}

const person: Person = { name: 'John', age: 30 };
const person2: Person = { name: 'Sara', age: 25,  gender: 'Women' };

การประกาศ Type ด้วย Interface

รูปแบบการใช้งาน interface:

  1. Declaration Merging
interface Car {
  brand: string;
}

interface Car {
  model: string;
}

const myCar: Car = {
  brand: 'Toyota',
  model: 'Camry',
};

การประกาศ Type ซ้ำ

  1. Extending Interfaces
interface Shape {
  color: string;
}

interface Square extends Shape {
  sideLength: number;
}

สืบทอดคุณสมบัติจาก interface อื่น

  1. Implements Keyword
interface Clock {
  currentTime: Date;
  setTime(d: Date): void;
}

class MyClock implements Clock {
  currentTime: Date = new Date();
  setTime(d: Date): void {
    this.currentTime = d;
  }
}

การใช้คีย์เวิร์ด implements เพื่อบังคับให้ class ปฏิบัติตามโครงสร้างของ interface

  1. Readonly Properties
interface Point {
  readonly x: number;
  readonly y: number;
}

สามารถทำให้ property เป็น readonly ได้

  1. Function Types
interface Calculate {
  (x: number, y: number): number;
}

ใช้ interface สำหรับกำหนดรูปแบบของฟังก์ชัน


Type

type aliases หรือ เรียกอีกชื่อว่า type เป็นเครื่องมือที่ช่วยในการสร้างชื่อใหม่สำหรับชนิดของข้อมูลที่มีอยู่แล้ว โดย type สามารถทำ Union Types, Intersection Types, และ Mapped Types ได้

โดยเราสามารถการประกาศ type ได้ดังนี้:

type Age = number;

type Person = {
  name: string;
  age: Age;
};

const myAge: Age = 25;
const person: Person = { name: 'John', age: myAge };

รูปแบบการใช้งาน type:

  1. Union Types
type Status = 'Pending' | 'Approved' | 'Rejected';

const currentStatus: Status = 'Approved';

การสร้าง Union Types

  1. Intersection Types
type Car = {
  brand: string;
};

type ElectricCar = {
  batteryLife: number;
} & Car;

const myCar: ElectricCar = {
  brand: 'Tesla',
  batteryLife: 300,
};

การสร้าง Intersection Types

  1. Declaration Merging (การประกาศซ้ำ)
type Person = { name: string };
type Person = { age: number };  // Declaration merging

การประกาศซ้ำ (declaration merging)

  1. Mapped Types:
type Flags = {
  option1: boolean;
  option2: boolean;
};

type FlagKeys = keyof Flags; // Mapped Type

การสร้างสร้าง Mapped Types


ความแตกต่างระหว่าง Interface กับ Type

ทั้ง type และ interface มีหน้าที่ทำงานที่คล้ายกัน แต่จะมีความแตกต่างกันอยู่บ้าง ขึ้นอยู่กับเราและทีมของเราเลยว่าอยากจะใช้งานแบบไหน หรือต้องการความสามารถอะไรจาก 2 ตัวนี้ เช่น

  • ถ้าคุณต้องการการใช้ extends หรือ implements ในการสร้างสิ่งที่สืบทอด, หรือต้องการมีการประกาศซ้ำกัน, interface อาจเป็นตัวเลือกที่ดี
  • ถ้าคุณต้องการใช้ Union, Intersection Types, หรือ Mapped Types, type อาจเป็นตัวเลือกที่ดี

Reference

https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-aliases