Function overload — bir nom, turli imzo

~20 daq · TypeScript · Funksiyalar

Matn formatlash funksiyasi yozmoqchisiz. String berilsa — katta harfga o'giradi. Massiv berilsa — har elementini katta harfga o'girib, birlashtirib qaytaradi:

function formatlash(kirish: string | string[]): string | string[] {
  if (typeof kirish === "string") return kirish.toUpperCase();
  return kirish.map(s => s.toUpperCase());
}

const natija = formatlash("salom");
natija.toUpperCase(); // ❌ — string | string[] — .toUpperCase() yo'q bo'lishi mumkin

Muammo: string bersak string qaytishini, string[] bersak string[] qaytishini TypeScript bilmaydi. Function overload bu muammoni hal qiladi.


Overload nima?

Bir funksiyaga bir nechta imzo (signature) yoziladi — har imzo turli argument va qaytish turini belgilaydi. TypeScript qaysi imzoga mos kelishini aniqlaydi:

// Overload imzolari
function formatlash(kirish: string):   string;
function formatlash(kirish: string[]): string[];

// Amalga oshirilish (implementation)
function formatlash(kirish: string | string[]): string | string[] {
  if (typeof kirish === "string") return kirish.toUpperCase();
  return kirish.map(s => s.toUpperCase());
}

Endi TypeScript tur biladi:

const a = formatlash("salom");     // string — TypeScript aniq biladi
const b = formatlash(["a", "b"]); // string[] — TypeScript aniq biladi

a.toUpperCase();  // ✅
b.map(s => s);    // ✅

Qanday ishlaydi

Chaqirilganda: formatlash("salom")
                      ↓
TypeScript imzolarni tekshiradi:
  1) formatlash(kirish: string): string   ← mos keldi ✅
  2) formatlash(kirish: string[]): string[]

Natija turi: string

Uch va undan ko'p imzo

function qayta(id: number):   Foydalanuvchi;
function qayta(email: string): Foydalanuvchi;
function qayta(faol: boolean): Foydalanuvchi[];

function qayta(kirish: number | string | boolean): Foydalanuvchi | Foydalanuvchi[] {
  if (typeof kirish === "number")  return db.findById(kirish);
  if (typeof kirish === "string")  return db.findByEmail(kirish);
  return db.findAll({ faol: kirish });
}

const user1 = qayta(1);           // Foydalanuvchi
const user2 = qayta("j@mail.com"); // Foydalanuvchi
const users = qayta(true);         // Foydalanuvchi[]

Implementation imzosi tashqaridan ko'rinmaydi

Foydalanuvchi faqat overload imzolarini ko'radi — implementation imzosi ichki:

function test(a: string): string;
function test(a: number): number;
function test(a: string | number): string | number {
  return a;
}

test("salom"); // ✅ — birinchi imzo
test(42);      // ✅ — ikkinchi imzo
test(true);    // ❌ — hech qaysi imzoga mos kelmaydi

Overload vs Union — qachon qaysi?

// Union — turlar bog'liq bo'lmasa
function chiqar(qiymat: string | number): void {
  console.log(qiymat);
}

// Overload — kirish turi natija turiga ta'sir qilsa
function formatlash(kirish: string):   string;
function formatlash(kirish: string[]): string[];
function formatlash(kirish: string | string[]): string | string[] { ... }

Overload kerak bo'lgan belgi: formatlash("x") string, formatlash(["x"]) string[] qaytarishi kerak — union bilan bu imkonsiz.


Tez-tez uchraydigan xatolar

Implementation imzosiz overload:

function fn(a: string): string;
function fn(a: number): number;
// ❌ — implementation yo'q, TypeScript xato beradi

Overload imzolardan keyin implementation majburiy.

Implementation imzosi overload imzosiga mos kelmasligi:

function fn(a: string): string;
function fn(a: number): number;
function fn(a: boolean): boolean { // ❌ — boolean imzosi yo'q
  return a;
}

Implementation barcha overload imzolarini qamrab olishi kerak.

Oddiy union bilan yechsa bo'ladigan joyda overload:

// ❌ — keraksiz murakkablik
function logla(x: string): void;
function logla(x: number): void;
function logla(x: string | number): void { console.log(x); }

// ✅ — union yetarli
function logla(x: string | number): void { console.log(x); }

Xulosa

// Imzolar — foydalanuvchi ko'radi
function fn(a: string):   string;
function fn(a: number):   number;
function fn(a: string[]): string[];

// Implementation — tashqaridan ko'rinmaydi
function fn(a: string | number | string[]): string | number | string[] {
  // ...
}

Overload — kirish turi natija turiga ta'sir qilganda. Har bir imzo: "bu parametr bersang, bu tur qaytadi" degan kafolat.


Keyingi dars

25-dars: Callback va higher-order funksiyalar tiplari