IlmHamroh
JavaScript Full-stack/15-qism. TypeScript10/47-dars18 daqiqa
Mundarija (28)

TypeScript strukturaviy tiplash: tur nomi emas, shakli muhim

Qisqacha: TypeScript'da ikki tur nomi bilan emas, shakli bilan solishtiriladi: kerakli xususiyatlari bor har qanday obyekt turga mos keladi. Bu strukturaviy tiplash (structural typing). { name: string; price: number } kutilgan joyga Dish klassi obyektini ham, ortiqcha xususiyatli oddiy obyektni ham berish mumkin. Teskari tomoni: shakli bir xil, lekin ma'nosi boshqa turlarni (so'm va foiz) TypeScript farqlamaydi.

Bu darsda

  • TypeScript turlarni qanday solishtirishini — "kamida shu xususiyatlar bor" qoidasini — tushunasiz.
  • Ko'proq xususiyatli obyekt nega mos, kamrog'i nega mos emasligini bilasiz.
  • Strukturaviy moslik va ortiqcha xususiyat tekshiruvi orasidagi farqni ajratasiz.
  • Klasslar ham shakl bo'yicha solishtirilishini va bundan kelib chiqadigan tuzoqni ko'rasiz.
  • "Nominal emaslik" muammosini taniysiz: bir xil shakldagi turli ma'nolar.

Oldin bilishingiz kerak: Funksiyalarni tiplash, Obyekt turlari, class sintaksisi.

1. Nega bu kerak?

Obyekt turlari darsida bir hodisaga duch keldik va "keyinroq" dedik. spicy xususiyati ortiqcha bo'lgan obyekt o'zgaruvchi orqali berilsa — xato yo'q edi. Funksiyalar darsida esa kamroq parametrli funksiya mos keldi. Ikkalasining ortida bitta qoida turibdi. Bugun uni ochamiz.

«Bahor» menyusida taomlar (Dish klassi), ichimliklar (oddiy obyektlar) va chekdagi qatorlar bor. Sardor narx taxtasini chiqaradigan funksiya yozdi:

ts
type Priced = { name: string; price: number };

function boardLine(item: Priced): string {
  return `${item.name}: ${item.price} so'm`;
}

class Dish {
  name: string;
  price: number;
  cookMinutes: number;
  constructor(name: string, price: number, cookMinutes: number) {
    this.name = name;
    this.price = price;
    this.cookMinutes = cookMinutes;
  }
}

const osh = new Dish("Osh", 35000, 40);
const tea = { name: "Ko'k choy", price: 5000, hot: true };
console.log(boardLine(osh));
console.log(boardLine(tea));

Konsolda:

text
Osh: 35000 so'm
Ko'k choy: 5000 so'm

Dish hech qayerda "men Priced man" demagan. tea ning esa umuman nomli turi yo'q. Lekin ikkalasi ham boardLine ga berildi va tsc indamadi. Java yoki C# kabi tillarda (boshqa dasturlash tillari — hozir bilish shart emas) bu ishlamasdi: u yerda klass "men shu turdanman" deb aniq e'lon qilishi kerak. TypeScript esa boshqacha savol beradi.

2. Shakl bo'yicha moslik

2.1 Savol: "kerakli xususiyatlar bormi?"

TypeScript osh ni Priced kutilgan joyga berishdan oldin bitta narsani tekshiradi: Priced talab qilgan har bir xususiyat osh da bormi va turi mosmi? name — bor, satr. price — bor, son. Demak, mos. cookMinutes va hot ga qaralmaydi — ular Priced uchun ortiqcha, xalaqit bermaydi.

Bu — strukturaviy tiplash (structural typing): tur tuzilishi (shakli) bo'yicha solishtiriladi. Uni "o'rdak tiplash" (duck typing) ham deyishadi: "o'rdakdek yursa va o'rdakdek g'ag'illasa — demak, o'rdak". Kundalik o'xshatish — kalit va qulf. Qulf kalitning rangi yoki egasini so'ramaydi, faqat tishlari mos kelishini tekshiradi.

2.2 Bir xil shakl — bir xil tur

Ikki xil nomli, lekin bir xil shakldagi tur bir-birining o'rnida ishlaydi:

ts
type MenuItem = { name: string; price: number };
type ReceiptLine = { name: string; price: number };

const line: ReceiptLine = { name: "Manti", price: 30000 };
const item: MenuItem = line;
console.log(item.name); // Manti

MenuItem va ReceiptLine — TypeScript uchun bitta tur, faqat ikki nomli. type va interface darsidagi "taxallus — yangi tur emas" qoidasi obyektlar uchun ham amal qiladi. interface bilan yozilgan bo'lsa ham xuddi shunday.

2.3 Ko'proq — mos, kamroq — yo'q

Yo'nalish muhim. Ko'proq xususiyatli obyekt kamroq talab qiladigan turga mos keladi, teskarisi — yo'q:

ts
type Priced = { name: string; price: number };

function boardLine(item: Priced): string {
  return `${item.name}: ${item.price} so'm`;
}

const water = { name: "Suv" };
boardLine(water);

Kompilyator:

text
TS2741: Property 'price' is missing in type '{ name: string; }' but required in type 'Priced'.

TypeScript aytyapti: «{ name: string; } turida price yo'q, Priced turida esa u majburiy».

water da price yo'q — funksiya item.price ni o'qisa, undefined olardi. Shuning uchun yetishmaydigan xususiyat har doim xato. Ortiqcha xususiyat esa xavfsiz: funksiya uni bilmaydi va ishlatmaydi.

Buni to'plamlar bilan tasavvur qiling. Tur — qiymatlar to'plami. Talab qancha ko'p bo'lsa, unga mos qiymatlar shuncha kam:

flowchart LR
  A["{ name }<br/>eng keng: nomi bor<br/>hamma narsa"] --> B["{ name; price }<br/>nomi va narxi bor"]
  B --> C["{ name; price; cookMinutes }<br/>eng tor: taomlar"]
  C -. "mos keladi ✅" .-> B
  B -. "mos keladi ✅" .-> A

O'qlar "torroq turni kengroq turga berish mumkin" degan yo'nalishni ko'rsatadi: har taom — narxli narsa, har narxli narsa — nomli narsa. Teskarisi esa yo'q: har nomli narsaning narxi bo'lavermaydi.

Tekshirib ko'ring: type Guest = { name: string } va const malika = { name: "Malika", phone: "+998 90 000 00 00" }; — const g: Guest = malika; xato beradimi? const back: typeof malika = g; chi?

Javob

Birinchisi — mos: malika da kerakli name bor, phone ortiqcha. Ikkinchisi — TS2741: Property 'phone' is missing in type 'Guest' but required in type '{ name: string; phone: string; }'. g ning turi faqat name ni kafolatlaydi — telefon bormi-yo'qmi, TypeScript bilmaydi.

3. Xususiyatlar turlari ham solishtiriladi

3.1 Har xususiyat — alohida

Xususiyat bor bo'lishi yetmaydi — uning turi ham mos bo'lishi kerak:

ts
type PriceTag = { name: string; price: string };

const fromKitchen = { name: "Osh", price: 35000 };
const tag: PriceTag = fromKitchen;

Kompilyator:

text
TS2322: Type '{ name: string; price: number; }' is not assignable to type 'PriceTag'.
  Types of property 'price' are incompatible.
    Type 'number' is not assignable to type 'string'.

Zanjirni pastdan o'qing: "son satrga mos emas" → "price xususiyatlarining turlari mos emas" → "butun obyekt mos emas". TypeScript ichma-ich obyektlarda ham xuddi shunday chuqurlashadi.

3.2 Ixtiyoriy va majburiy

ts
type Priced = { name: string; price: number };
type MaybePriced = { name: string; price?: number };

const gift: MaybePriced = { name: "Non" };
const priced: Priced = gift;

Kompilyator:

text
TS2322: Type 'MaybePriced' is not assignable to type 'Priced'.
  Types of property 'price' are incompatible.
    Type 'number | undefined' is not assignable to type 'number'.
      Type 'undefined' is not assignable to type 'number'.

MaybePriced ning price i — number | undefined, Priced esa aniq son kutadi. Teskari yo'nalish — Priced dan MaybePriced ga — mos: narxi bor narsa "narxi bo'lishi mumkin" degan turga sig'adi.

3.3 Massivlar va funksiyalar

Qoida hamma joyda bir xil. Dish[] ni readonly Priced[] parametrga berish mumkin — har element mos. Funksiyalar ham shakli bo'yicha solishtiriladi: o'tgan darsdagi "kamroq parametrli funksiya mos" qoidasi — strukturaviy tiplashning funksiyalardagi ko'rinishi.

Qayerdan → qayerga Mosmi Nega
{ name; price; hot } → { name; price } ortiqcha xususiyat xalaqit bermaydi
{ name } → { name; price } TS2741 price yetishmaydi
{ price?: number } → { price: number } TS2322 undefined bo'lishi mumkin
{ price: number } → { price?: number } son — "son yoki yo'q" ga sig'adi
Dish[] → readonly Priced[] har element mos

4. Ortiqcha xususiyat tekshiruvi bilan farqi

Endi Obyekt turlari darsidagi jumboq yechiladi. Bir xil obyekt, ikki xil natija:

ts
type Priced = { name: string; price: number };

const viaVariable = { name: "Choy", price: 5000, hot: true };
const ok: Priced = viaVariable;
const fresh: Priced = { name: "Choy", price: 5000, hot: true };

Kompilyator:

text
TS2353: Object literal may only specify known properties, and 'hot' does not exist in type 'Priced'.

TypeScript aytyapti: «obyekt literali faqat ma'lum xususiyatlarni yozishi mumkin, Priced da esa hot yo'q».

Faqat uchinchi qator xato. Moslik qoidasi bo'yicha ikkalasi ham to'g'ri: name va price bor. Lekin yangi yozilgan literalga (freshness) TypeScript qo'shimcha tekshiruv qo'llaydi. Yangi literaldagi ortiqcha xususiyatni hech kim ko'rmaydi — u darhol yo'qoladi, demak bu deyarli aniq imlo xatosi.

Strukturaviy moslik Ortiqcha xususiyat tekshiruvi
Nimani tekshiradi kerakli xususiyatlar bormi ortiqcha xususiyat bormi
Qachon doim faqat yangi obyekt literalida
Maqsad xavfsizlik (undefined o'qilmasin) imlo xatolarini ushlash

Shu sababli massiv ichidagi literallar ham tekshiriladi: cheapest([{ name: "Osh", price: 1, hot: true }]) — TS2353, chunki bu literallar ham shu joyda yaratilgan.

5. Klasslar ham shakl bo'yicha

5.1 Klass turi — uning ochiq xususiyatlari

TypeScript'da klass nomi ham shakl sifatida ishlaydi. Klass obyekti kutilgan joyga oddiy obyekt berish mumkin:

ts
class Dish {
  name: string;
  price: number;
  constructor(name: string, price: number) {
    this.name = name;
    this.price = price;
  }
}

const fake: Dish = { name: "Osh", price: 35000 };
console.log(fake instanceof Dish); // false

tsc — xatosiz: fake da Dish ning hamma xususiyatlari bor. Lekin ishlash paytida u Dish emas — instanceof false qaytardi (instanceof prototip zanjirini tekshiradi). Klassda metod bo'lsa, oddiy obyektda ham o'sha metod bo'lishi kerak — aks holda TS2741.

5.2 Yopiq # maydon shaklni "noyob" qiladi

Yopiq # maydonli klass bilan bunday qilib bo'lmaydi:

ts
class Receipt {
  #number = 1;
  guest = "Malika";
}

const forged: Receipt = { guest: "Malika" };

Kompilyator:

text
TS2741: Property '#number' is missing in type '{ guest: string; }' but required in type 'Receipt'.

TypeScript aytyapti: «{ guest: string; } da #number yo'q, Receipt da esa u majburiy».

#number ni klassdan tashqarida hech kim yarata olmaydi. Shuning uchun yopiq maydonli klass turi amalda faqat o'z obyektlariga mos keladi. Klasslarni TypeScript'da batafsil — Klasslar TypeScript'da darsida.

Tekshirib ko'ring: class Table { seats = 4; #id = 7; } va class Booth { seats = 4; } berilgan. const t: Booth = new Table(); mosmi? const b: Table = new Booth(); chi?

Javob

Birinchisi — mos: Booth faqat seats ni talab qiladi, Table da u bor (#id — ortiqcha, xalaqit bermaydi). Ikkinchisi — TS2741: Property '#id' is missing in type 'Booth' but required in type 'Table'. Ikki klass bir-biridan meros olmagan, lekin birinchi yo'nalishda shakl yetarli. Ikkinchisida yopiq maydon yo'q — mos emas.

5.3 vazifalar da: Vazifa va Saralanadigan

Bu qoida vazifalar da allaqachon ishlayapti. saralash.js Vazifa klassini import ham qilmaydi — u faqat shaklni tasvirlaydi:

js
/**
 * @typedef {object} Saralanadigan
 * @property {number} id qo'shilish tartibi: kattasi — yangisi
 * @property {string} matn
 * @property {boolean} bajarildi
 */

royxat.js tartibla ga Vazifa klassi obyektlarini beradi (matn — getter), testlar esa oddiy obyektlarni: ({ id, matn, bajarildi }). Ikkalasi ham Saralanadigan ga mos. Modul klassga bog'lanmagan — uni klassiz ham sinash mumkin. Generics va cheklovlar qadamida saralash .ts ga o'tganda ham shu qoladi: Taqqoslovchi = (a: VazifaMalumoti, b: VazifaMalumoti) => number, Vazifa esa import qilinmaydi.

6. TypeScript nimani ushlamaydi: nominal emaslik

Strukturaviy tiplashning narxi — bir xil shakldagi turli ma'nolarni TypeScript ajratmaydi:

ts
type Sum = { amount: number }; // so'mda
type Percent = { amount: number }; // foizda

function addService(bill: Sum, service: Percent): number {
  return bill.amount + (bill.amount * service.amount) / 100;
}

const bill: Sum = { amount: 70000 };
const service: Percent = { amount: 10 };
console.log(addService(service, bill)); // 7010

Argumentlar almashib ketdi — 10 so'mlik hisobga 70 000 % xizmat haqi. tsc jim: ikkala tur ham { amount: number }. Bu nominal emaslik: TypeScript'da tur nomi tekshiruvga ta'sir qilmaydi.

Ikkinchi misol — keng tur bilan ortiqcha ma'lumotni "yo'qotish":

ts
type Priced = { name: string; price: number };

function total(items: readonly Priced[]): number {
  return items.reduce((sum, item) => sum + item.price, 0);
}

const lines = [{ name: "Somsa", price: 8000, qty: 3 }];
console.log(total(lines)); // 8000

Chek qatorida 3 ta somsa, jami esa 8 000 — qty ga hech kim qaramadi. lines Priced[] ga mos, chunki ortiqcha qty xalaqit bermaydi. Mantiq xatosini TypeScript topmaydi.

Himoya yo'llari:

  • Nom bilan farqlovchi maydon: { kind: "sum"; amount: number } va { kind: "percent"; amount: number } — endi shakllar har xil. Bu g'oya — Discriminated union darsida.
  • Brend turlar — faqat tur darajasidagi "yorliq": Branded types darsida.
  • Obyekt parametr: addService({ bill, service }) — nomlar bilan berilgan argumentlar adashmaydi.

7. Ko'p uchraydigan xatolar

7.1 Parametrga klass turini yozish

function cheapest(items: Dish[]) — endi ichimliklarni berib bo'lmaydi (TS2741 … 'cookMinutes' is missing). Tuzatish: funksiya faqat ishlatadigan xususiyatlarni talab qilsin — readonly Priced[]. Shunda u taomlar, ichimliklar va testdagi oddiy obyektlar bilan ishlaydi.

7.2 "Turini e'lon qilmagan — demak mos emas" deb o'ylash

implements yoki extends yozilmagani moslikka ta'sir qilmaydi. Tuzatish: xabardagi yetishmaydigan yoki mos kelmaydigan xususiyatga qarang.

7.3 Tur nomi himoya qiladi deb o'ylash

type OrderId = { value: number } va type TableId = { value: number } — bitta tur. Tuzatish: farqlovchi maydon yoki brend tur.

7.4 instanceof ga ishonish

Tur Dish deydi, qiymat esa oddiy obyekt bo'lishi mumkin — instanceof false. Tuzatish: klass obyekti kerak bo'lsa, uni new bilan yarating yoki # maydon qo'shing.

8. Mashqlar

1-mashq (oson): Mos keladimi?

type Contact = { name: string; phone: string }; berilgan.

const a = { name: "Bobur", phone: "+998 90 000 00 00", vip: true }; const c: Contact = a; — xato bormi (ha/yo'q): [:yo'q]. const c2: Contact = { name: "Ali" }; xatosining kodi: TS[:2741]. const c3: Contact = { name: "Ali", phone: "x", vip: true }; xatosining kodi: TS.

Yechim
  • a — o'zgaruvchi, kerakli name va phone bor, vip ortiqcha: strukturaviy moslik — xatosiz.
  • { name: "Ali" } — phone yetishmaydi: TS2741.
  • Uchinchisi — yangi literal va ortiqcha vip: ortiqcha xususiyat tekshiruvi, TS2353.

2-mashq (o'rta): Nega cookMinutes yo'qoldi?

ts
type Priced = { name: string; price: number };
type Dish = { name: string; price: number; cookMinutes: number };

function cheapest(items: readonly Priced[]): Priced | undefined {
  let best: Priced | undefined;
  for (const item of items) {
    if (best === undefined || item.price < best.price) best = item;
  }
  return best;
}

const dishes: Dish[] = [
  { name: "Osh", price: 35000, cookMinutes: 40 },
  { name: "Manti", price: 30000, cookMinutes: 50 },
];
console.log(cheapest(dishes)?.cookMinutes);

Kompilyator:

text
TS2339: Property 'cookMinutes' does not exist on type 'Priced'.

(1) dishes ni cheapest ga berish nega xatosiz? (2) Natijada cookMinutes nega "yo'qoldi", garchi ishlash paytida u bor bo'lsa ham? (3) Hozirgi bilim bilan tuzating.

Yechim

(1) Har Dish — Priced ga mos: kerakli name va price bor (strukturaviy moslik).

(2) Funksiyaning natija turi — Priced. TypeScript funksiya ichiga qaramaydi, faqat imzoga: "qaytgan narsa — Priced". Haqiqiy obyektda cookMinutes bor, lekin tur uni "unutdi".

(3) Hozircha — natijani Dish sifatida ishlatadigan alohida funksiya:

ts
type Dish = { name: string; price: number; cookMinutes: number };

function cheapestDish(items: readonly Dish[]): Dish | undefined {
  let best: Dish | undefined;
  for (const item of items) {
    if (best === undefined || item.price < best.price) best = item;
  }
  return best;
}

const dishes: Dish[] = [
  { name: "Osh", price: 35000, cookMinutes: 40 },
  { name: "Manti", price: 30000, cookMinutes: 50 },
];
console.log(cheapestDish(dishes)?.cookMinutes); // 50

Ishlaydi, lekin endi ikki deyarli bir xil funksiya. "Qanday tur bersang, o'shani qaytaraman" degan bitta funksiya yozish yo'li bor — Generics: turni parametr qilish darsida. Bu mashq o'sha darsning sababi.

3-mashq (qiyin): Amaliy tajriba — menyu taxtasi

Mashq kurs/mashqlar/15/ da. Sardor 10-strukturaviy/board.ts da eng arzon narsani topadigan funksiyani "klass bilan" yozdi:

ts
// 10-strukturaviy/board.ts — «Bahor» menyu taxtasi
export class Dish {
  readonly name: string;
  readonly price: number;
  readonly cookMinutes: number;
  constructor(name: string, price: number, cookMinutes: number) {
    this.name = name;
    this.price = price;
    this.cookMinutes = cookMinutes;
  }
}

export function cheapest(items: readonly Dish[]): Dish | undefined {
  let best: Dish | undefined;
  for (const item of items) {
    if (best === undefined || item.price < best.price) best = item;
  }
  return best;
}

Va test — taomlar va ichimlik birga:

ts
// 10-strukturaviy/board.test.ts (birinchi variant)
import { test } from "node:test";
import assert from "node:assert/strict";
import { Dish, cheapest } from "./board.ts";

const osh = new Dish("Osh", 35000, 40);
const tea = { name: "Ko'k choy", price: 5000, hot: true };

test("cheapest: taomlar va ichimlik birga", () => {
  assert.equal(cheapest([osh, tea])?.name, "Ko'k choy");
});
  1. npx tsc --pretty false — xatoni o'qing. Muammo testdami yoki funksiyada?
  2. export type Priced ni e'lon qiling va cheapest faqat kerakli shaklni talab qilsin.
  3. boardLines(items) qo'shing: har narsa uchun "Nomi: narx so'm" qatori.
  4. Testlar: aralash ro'yxat va faqat taomlar; bo'sh ro'yxat; boardLines ortiqcha xususiyatlarni yozmasligi; instanceof klass obyektini oddiy obyektdan farqlashi.
Yechim

1-qadamda tsc 7.0.2:

text
10-strukturaviy/board.test.ts(10,31): error TS2741: Property 'cookMinutes' is missing in type '{ name: string; price: number; hot: boolean; }' but required in type 'Dish'.

Xato test faylida chiqdi, lekin muammo — funksiyada. cheapest faqat price ni ishlatadi, parametri esa Dish ning hamma xususiyatini (cookMinutes ham) talab qilyapti. Bu «Parametrga klass turini yozish» xatosi.

ts
// 10-strukturaviy/board.ts — «Bahor» menyu taxtasi
// Narxi bor har narsa: taom, ichimlik, sovg'a to'plami...
export type Priced = {
  readonly name: string;
  readonly price: number;
};

export class Dish {
  readonly name: string;
  readonly price: number;
  readonly cookMinutes: number;
  constructor(name: string, price: number, cookMinutes: number) {
    this.name = name;
    this.price = price;
    this.cookMinutes = cookMinutes;
  }
}

export function cheapest(
  items: readonly Priced[],
): Priced | undefined {
  let best: Priced | undefined;
  for (const item of items) {
    if (best === undefined || item.price < best.price) best = item;
  }
  return best;
}

export function boardLines(items: readonly Priced[]): string[] {
  return items.map((item) => `${item.name}: ${item.price} so'm`);
}

Dish va Priced orasida hech qanday bog'lanish yozilmagan — ular faqat shakl bo'yicha mos.

ts
// 10-strukturaviy/board.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import { Dish, cheapest, boardLines } from "./board.ts";

const osh = new Dish("Osh", 35000, 40);
const manti = new Dish("Manti", 30000, 50);
const tea = { name: "Ko'k choy", price: 5000, hot: true };

test("cheapest: klass obyekti va oddiy obyekt birga", () => {
  assert.equal(cheapest([osh, manti, tea])?.name, "Ko'k choy");
  assert.equal(cheapest([osh, manti])?.name, "Manti");
});

test("cheapest: bo'sh ro'yxat — undefined", () => {
  assert.equal(cheapest([]), undefined);
});

test("boardLines: ortiqcha xususiyatlar yozilmaydi", () => {
  assert.deepEqual(boardLines([osh, tea]), [
    "Osh: 35000 so'm",
    "Ko'k choy: 5000 so'm",
  ]);
});

test("Dish — klass, tea — yo'q: instanceof farqlaydi", () => {
  assert.equal(osh instanceof Dish, true);
  assert.equal(tea instanceof Dish, false);
});

tea ni oldin o'zgaruvchiga oldik. Agar uni to'g'ridan-to'g'ri yozsangiz — cheapest([osh, { name: "Ko'k choy", price: 5000, hot: true }]) — TS2353 chiqadi: massiv ichidagi yangi literal ortiqcha xususiyat tekshiruvidan o'tadi. npx tsc --pretty false — chiqishsiz. node --test 10-strukturaviy/board.test.ts — bizda (Node 24.21.0):

text
✔ cheapest: klass obyekti va oddiy obyekt birga (2.7879ms)
✔ cheapest: bo'sh ro'yxat — undefined (0.4596ms)
✔ boardLines: ortiqcha xususiyatlar yozilmaydi (2.5257ms)
✔ Dish — klass, tea — yo'q: instanceof farqlaydi (0.4442ms)
ℹ tests 4
ℹ suites 0
ℹ pass 4
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 334.5347

XATOLAR.md ga bu darsdagi zanjirli xabarni qo'shing: TS2322 … Types of property 'price' are incompatible, va TS2741 ning # maydonli ko'rinishi. Keyin kurs/mashqlar papkasidan:

bash
git add 15/10-strukturaviy 15/XATOLAR.md
git commit -m "15/10: board.ts — strukturaviy moslik, Priced"

9. Real ishda

  • Testlar — strukturaviy tiplashning eng katta yutug'i: haqiqiy klass o'rniga oddiy obyekt (soxta ma'lumot — mock) berish mumkin, vazifalar dagi saralash testlari kabi.
  • Kutubxonalar bilan ishlash: kutubxona { x: number; y: number } kutsa, o'zingizning Point klassingiz ham, oddiy obyekt ham mos keladi — hech qanday "adapter" yozilmaydi.
  • API javoblari odatda o'zingiz yozgan turga strukturaviy moslanadi. Lekin moslik faqat kompilyatsiyada tekshiriladi — ishlash paytidagi ma'lumot boshqacha bo'lishi mumkin (API ma'lumotlarini tiplash).
  • Intervyu: "Structural va nominal typing farqi?", "Nega ortiqcha xususiyatli obyekt ba'zan xato beradi, ba'zan yo'q?" — TypeScript intervyusining klassik savollari.

Xulosa

  • TypeScript turlarni shakl bo'yicha solishtiradi: kerakli xususiyatlar bor va turlari mos bo'lsa — mos. Nomi va kelib chiqishi ahamiyatsiz.
  • Ko'proq xususiyat — mos, yetishmaydigan xususiyat — TS2741. Xususiyat turlari ham, ixtiyoriylik ham tekshiriladi.
  • Ortiqcha xususiyat tekshiruvi — alohida qoida, faqat yangi obyekt literalida (TS2353).
  • Klass turi — uning ochiq xususiyatlari: oddiy obyekt ham mos keladi, lekin instanceof farqlaydi. # maydon klassni "noyob" qiladi.
  • Nominal emaslik: bir xil shakldagi turli ma'nolarni (so'm va foiz) TypeScript ajratmaydi — farqlovchi maydon yoki brend tur kerak.

Keyingi dars: Narrowing: turni toraytirish — typeof, in, instanceof va tenglik tekshiruvlaridan keyin TypeScript union turini qanday aniqroq turga toraytirishini ko'ramiz.

Manbalar

  • TypeScript Handbook: "Type Compatibility" — typescriptlang.org/docs/handbook/type-compatibility.html
  • TypeScript Handbook: "Object Types" → Excess Property Checks — typescriptlang.org/docs/handbook/2/objects.html
  • TypeScript FAQ: "Why doesn't type checking reject … nominal types?" — github.com/microsoft/TypeScript/wiki/FAQ
  • TypeScript Handbook: "Classes" → Relationships Between Classes — typescriptlang.org/docs/handbook/2/classes.html
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
TypeScript strukturaviy tiplash: tur nomi emas, shakli muhim — IlmHamroh