TypeScript / Interface өвлөлт

Interface өвлөлт

Апп томроход олон interface хоорондоо давхардах шинж чанартай болдог. Жишээ нь Хэрэглэгч, Ажилтан, Админ гурав нь нэр, и_мэйл зэрэг нийтлэг шинж чанартай. Эдгээрийг давтан бичихийн оронд interface өвлөлт ашиглана.

extends түлхүүр үг

Нэг interface өөр interface-аас extends ашиглан шинж чанаруудыг "өвлөнө":

typescript
interface Хүн {
  нэр: string;
  нас: number;
}

interface Суралцагч extends Хүн {
  сургууль: string;
  дүн: number;
}

// Суралцагч нь Хүн-ий бүх шинж чанарыг агуулна
const суралцагч: Суралцагч = {
  нэр: "Болд", // Хүн-ээс өвлөсөн
  нас: 20, // Хүн-ээс өвлөсөн
  сургууль: "МУИС",
  дүн: 3.7,
};

Суралцагч extends Хүн гэдэг нь "Хүн-ий бүх зүйлийг авч, дээр нь нэмнэ" гэсэн утгатай. нэр ба нас-г давтан бичих шаардлагагүй.

Олон interface-аас өвлөх

TypeScript interface олон эх сурвалжаас зэрэг өвлөж болно:

typescript
interface Хаяг {
  хот: string;
  улс: string;
}

interface Холбоо Барих {
  и_мэйл: string;
  утас?: string;
}

interface Хэрэглэгч extends Хаяг, Холбоо Барих {
  id: string;
  нэр: string;
}

const хэрэглэгч: Хэрэглэгч = {
  id: "usr_001",
  нэр: "Сарнай",
  хот: "Улаанбаатар",  // Хаяг-аас
  улс: "Монгол",        // Хаяг-аас
  и_мэйл: "sarnai@example.mn", // Холбоо Барих-аас
  // утас заавал биш тул орхиж болно
};

Нэг comma-аар extends Хаяг, Холбоо Барих гэж бичихэд хоёуланг нь өвлөнө.

Гүнзгий өвлөлт

Interface өвлөлт хэд хэдэн давхаргатай байж болно:

typescript
interface Амьтан {
  нэр: string;
  нас: number;
}

interface Тэжээвэр Амьтан extends Амьтан {
  эзэн: string;
  вакцинжуулсан: boolean;
}

interface Нохой extends Тэжээвэр Амьтан {
  үүлдэр: string;
  сургагдсан: boolean;
}

const нохой: Нохой = {
  нэр: "Тасхай",         // Амьтан-аас
  нас: 3,                // Амьтан-аас
  эзэн: "Мөнхбат",      // Тэжээвэр Амьтан-аас
  вакцинжуулсан: true,   // Тэжээвэр Амьтан-аас
  үүлдэр: "Хаски",
  сургагдсан: true,
};

Нохой → Тэжээвэр Амьтан → Амьтан гэсэн гинж үүснэ. Эхний хоёр interface-ийн шинж чанарыг Нохой автоматаар агуулна.

Interface өвлөж шинж чанар өөрчлөх

Өвлөсөн шинж чанарыг нарийвчлуулж болно — гэхдээ any болгох эсвэл нийцэхгүй төрлөөр солих боломжгүй:

typescript
interface Амьтан {
  дуу: string;
}

interface Муур extends Амьтан {
  дуу: "миаа" | "хурр"; // Нарийвчилна — string-ийн дэд хэсэг тул зөв
}

const муур: Муур = {
  дуу: "миаа", // зөв
};

// Муур нь Амьтан-д нийцнэ — учир нь "миаа" нь string юм
const амьтан: Амьтан = муур; // зөв

Бодит жишээ: хэрэглэгчийн эрхийн систем

Өвлөлт хамгийн их хэрэгтэй газрын нэг бол хэрэглэгчийн эрхийн систем:

typescript
interface ҮндсэнХэрэглэгч {
  readonly id: string;
  нэр: string;
  и_мэйл: string;
  үүссэн огноо: string;
}

interface Суралцагч extends ҮндсэнХэрэглэгч {
  xp: number;
  дүүргэсэн хичээлүүд: string[];
  эрэмбэ: "шинэхэн" | "дунд" | "ахисан";
}

interface Багш extends ҮндсэнХэрэглэгч {
  мэргэжил: string;
  курсүүд: string[];
  баталгаажсан: boolean;
}

interface Админ extends ҮндсэнХэрэглэгч {
  эрхийн түвшин: 1 | 2 | 3;
  хамрах хүрээ: string[];
}

function хэрэглэгч харах(хэрэглэгч: ҮндсэнХэрэглэгч): void {
  console.log(`${хэрэглэгч.нэр} (${хэрэглэгч.и_мэйл})`);
}

const суралцагч: Суралцагч = {
  id: "usr_001",
  нэр: "Энхтүвшин",
  и_мэйл: "enkh@example.mn",
  үүссэн огноо: "2024-01-10",
  xp: 450,
  дүүргэсэн хичээлүүд: ["01-intro", "02-setup"],
  эрэмбэ: "шинэхэн",
};

// Суралцагч нь ҮндсэнХэрэглэгч-г өвлөсөн тул энд дамжуулж болно
хэрэглэгч харах(суралцагч); // Энхтүвшин (enkh@example.mn)

хэрэглэгч харах функц ҮндсэнХэрэглэгч авдаг тул Суралцагч, Багш, Админ бүгдийг дамжуулж болно. Код нэгтгэгдэж, давтагдахгүй.

extends ба & (intersection) ялгаа

Хоёулаа интерфейсүүдийг нэгтгэдэг боловч:

typescript
// Interface extends — өвлөлт, тодорхой харилцаа
interface А {
  x: number;
}
interface В extends А {
  y: string;
} // В нь А юм

// Intersection — нэгтгэлт, шинэ нэр байхгүй
type АбаВ = А & { y: string }; // АбаВ нь А биш, хоёуланг нь агуулна

Объектын шаталсан бүтэц (is-a харилцаа) тодорхойлоход extends, хоёр тусдаа зүйлийг нэгтгэхэд & ашиглах нь илүү тохиромжтой.

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

Type alias ба Interface хоёрын нарийн ялгааг харьцуулж, хэзээ алийг нь ашиглах вэ гэдгийг дүгнэнэ. Энэ бол TypeScript-д хамгийн их асуугддаг асуулт юм.