TypeScript / Function Overloading

Function Overloading

Заримдаа нэг функц өөр өөр төрлийн параметр авч, тус бүрдээ өөр төрлийн утга буцаах хэрэгтэй болдог. TypeScript-д энэ асуудлыг function overloading аргаар шийдэж болно.

Overloading гэж юу вэ?

Нэг нэртэй, гэхдээ өөр өөр параметртэй хэд хэдэн функцийн "гарын үсэг" (signature) тодорхойлох аргыг overloading гэнэ:

typescript
// Overload signature-үүд — хэрэгжилтгүй зүгээр тодорхойлолт
function боловсруул(утга: string): string;
function боловсруул(утга: number): number;

// Implementation signature — бодит хэрэгжилт
function боловсруул(утга: string | number): string | number {
  if (typeof утга === "string") {
    return утга.toUpperCase();
  }
  return утга * 2;
}

console.log(боловсруул("сайн уу")); // "САЙН УУ"
console.log(боловсруул(5)); // 10

Хамгийн дээрх хоёр мөр — overload signature. Сүүлийн функц — implementation. Хэрэглэгч зөвхөн overload signature-үүдийг харна, implementation нуугддаг.

Жишээ: утгын төрлөөс хамаарсан буцаалт

typescript
// Нас авч, тодорхойлолт буцаана
function насны_мэдээлэл(нас: number): string;
// Мөр авч, тоо буцаана
function насны_мэдээлэл(мэдэгдэл: string): number;

function насны_мэдээлэл(утга: number | string): string | number {
  if (typeof утга === "number") {
    if (утга < 18) return "Насанд хүрээгүй";
    if (утга < 65) return "Насанд хүрсэн";
    return "Ахмад настан";
  }
  // Мөрөөс насыг задлан буцаана
  return parseInt(утга, 10);
}

console.log(насны_мэдээлэл(15)); // "Насанд хүрээгүй"
console.log(насны_мэдээлэл(30)); // "Насанд хүрсэн"
console.log(насны_мэдээлэл("25")); // 25

Optional параметртэй overloading

Overloading нь optional параметрийн оронд илүү тод тодорхойлолт өгдэг:

typescript
// Optional параметр ашиглавал буцаах төрөл тодорхойгүй болно
function хайх(нэр: string, яг_таарсан?: boolean): string | string[] {
  // ...
}

// Overloading ашиглавал илүү тодорхой
function хайх(нэр: string): string[];
function хайх(нэр: string, яг_таарсан: true): string;
function хайх(нэр: string, яг_таарсан?: boolean): string | string[] {
  const бүх_нэрс = ["Болд", "Бат", "Бямба", "Болормаа"];
  if (яг_таарсан) {
    return бүх_нэрс.find((н) => н === нэр) ?? "";
  }
  return бүх_нэрс.filter((н) => н.startsWith(нэр[0]));
}

const олдсон: string = хайх("Болд", true); // string
const олдсон_бүгд: string[] = хайх("Б"); // string[]

TypeScript яг ямар төрөл буцааж байгааг ойлгож, IDE автоматаар зөв төрлийг санал болгоно.

Class method дахь overloading

typescript
class Текст_боловсруулагч {
  // Overload signature-үүд
  хөрвүүл(утга: string): number;
  хөрвүүл(утга: number): string;

  // Implementation
  хөрвүүл(утга: string | number): string | number {
    if (typeof утга === "string") {
      return parseInt(утга, 10) || 0;
    }
    return утга.toString();
  }
}

const боловсруулагч = new Текст_боловсруулагч();
const тоо: number = боловсруулагч.хөрвүүл("42"); // 42
const мөр: string = боловсруулагч.хөрвүүл(42); // "42"

Хэзээ overloading хэрэглэх вэ?

Overloading нь бүх нөхцөлд хэрэгтэй биш. Энгийн тохиолдолд union type хангалттай:

typescript
// Энгийн тохиолдолд — union type хангалттай
function хэвлэх(утга: string | number): void {
  console.log(утга);
}

// Overloading хэрэгтэй тохиолдол — буцаах төрөл параметрээс хамаарах үед
function задлах(утга: string): string[];
function задлах(утга: string[]): string;
function задлах(утга: string | string[]): string | string[] {
  if (Array.isArray(утга)) return утга.join(", ");
  return утга.split(", ");
}

Overloading нь TypeScript-ийн хүчирхэг боловч нарийн онцлог. Ойлгож суралцсанаар API дизайн хийх ур чадвар мэдэгдэхүйц дэвшинэ.

Дараагийн хичээлд:

TypeScript-д класс хэрхэн тодорхойлох, constructor, property, method-д яаж төрлийг нэмэхийг сурна.