Skip to content

Type Checking in TypeScript (การตรวจสอบประเภท)

เทคนิคการตรวจสอบประเภทข้อมูลใน TypeScript ที่ช่วยให้โค้ดปลอดภัยและทำงานถูกต้อง

1. Basic Type Checking (พื้นฐาน)

typeof Operator

ts
function printLength(value: string | number) {
  if (typeof value === "string") {
    // ภายในนี้ TypeScript รู้ว่า value เป็น string
    console.log(value.length);
  } else {
    // ภายในนี้ TypeScript รู้ว่า value เป็น number
    console.log(value.toFixed(2));
  }
}

การใช้งาน:

  • ใช้ตรวจสอบ primitive types (string, number, boolean, etc.)
  • ทำงานขณะ runtime

instanceof Operator

ts
class ApiError extends Error {
  statusCode: number;
  constructor(message: string, statusCode: number) {
    super(message);
    this.statusCode = statusCode;
  }
}

function handleError(error: Error) {
  if (error instanceof ApiError) {
    // รู้ว่าเป็น ApiError และมี property statusCode
    console.log(`API Error: ${error.statusCode}`);
  } else {
    // เป็น Error ธรรมดา
    console.log(error.message);
  }
}

2. User-Defined Type Guards (การสร้างตัวตรวจสอบเอง)

Function Type Guard

ts
interface Cat {
  meow(): void;
}

interface Dog {
  bark(): void;
}

function isCat(animal: Cat | Dog): animal is Cat {
  return (animal as Cat).meow !== undefined;
}

function animalSound(animal: Cat | Dog) {
  if (isCat(animal)) {
    animal.meow(); // TypeScript รู้ว่าเป็น Cat
  } else {
    animal.bark(); // TypeScript รู้ว่าเป็น Dog
  }
}

in Operator

ts
interface Admin {
  role: string;
  permissions: string[];
}

interface User {
  name: string;
  email: string;
}

function checkAccess(person: Admin | User) {
  if ("role" in person) {
    // รู้ว่าเป็น Admin
    console.log(person.permissions);
  } else {
    // รู้ว่าเป็น User
    console.log(person.email);
  }
}

3. Advanced Techniques (เทคนิคขั้นสูง)

Discriminated Unions

ts
type SuccessResponse = {
  status: "success";
  data: unknown;
};

type ErrorResponse = {
  status: "error";
  message: string;
};

type ApiResponse = SuccessResponse | ErrorResponse;

function handleResponse(response: ApiResponse) {
  switch (response.status) {
    case "success":
      console.log(response.data); // รู้ว่าเป็น SuccessResponse
      break;
    case "error":
      console.error(response.message); // รู้ว่าเป็น ErrorResponse
      break;
  }
}

Type Predicates

ts
function isStringArray(value: unknown): value is string[] {
  return Array.isArray(value) && value.every(item => typeof item === "string");
}

function processArray(value: unknown) {
  if (isStringArray(value)) {
    // รู้ว่าเป็น string[]
    value.map(str => str.toUpperCase());
  }
}

4. Type Predicates (การยืนยันประเภท)

ใช้สร้างฟังก์ชันที่บอก TypeScript ว่า value เป็น type อะไร

ts
function isString(value: unknown): value is string {
  return typeof value === "string";
}

const input: unknown = "hello";
if (isString(input)) {
  // ภายในนี้ input เป็น string
  console.log(input.toUpperCase());
}

5. Null Checks (การตรวจสอบค่า null/undefined)

TypeScript มี strict null checks เพื่อป้องกัน errors

ts
function greet(name: string | null) {
  if (name === null) {
    // ตรวจสอบก่อนใช้
    return "Hello, Guest!";
  }
  // ภายในนี้ name เป็น string เท่านั้น
  return `Hello, ${name.toUpperCase()}!`;
}

6. Type Assertions (การยืนยันประเภทแบบตรงๆ)

ใช้เมื่อเรารู้ type แน่นอนกว่า TypeScript

ts
const element = document.getElementById("my-input") as HTMLInputElement;
// บอก TypeScript ว่า element เป็น HTMLInputElement
console.log(element.value);

7. never Type (การตรวจสอบ exhaustiveness)

ช่วยตรวจสอบว่าเราได้จัดการทุกกรณีที่เป็นไปได้

ts
type Shape = Circle | Square;

interface Circle {
  kind: "circle";
  radius: number;
}

interface Square {
  kind: "square";
  sideLength: number;
}

function getArea(shape: Shape) {
  switch (shape.kind) {
    case "circle":
      return Math.PI * shape.radius ** 2;
    case "square":
      return shape.sideLength ** 2;
    default:
      // TypeScript จะเตือนถ้ามี case ใหม่แต่ไม่ได้จัดการ
      const _exhaustiveCheck: never = shape;
      return _exhaustiveCheck;
  }
}

8. Common Patterns (รูปแบบที่พบบ่อย)

Null Checks

ts
function getLength(text?: string | null) {
  if (text == null) { // ตรวจสอบทั้ง null และ undefined
    return 0;
  }
  return text.length;
}

Optional Chaining

ts
interface User {
  profile?: {
    name?: string;
    age?: number;
  };
}

function getUserName(user: User): string {
  return user.profile?.name ?? "Unknown";
}