IlmHamroh
JavaScript Full-stack/15-qism. TypeScript23/47-dars17 daqiqa
Mundarija (34)

TypeScript generics amaliyoti: const tur parametri, NoInfer va keraksiz generic

Qisqacha: Generic'lar ikki yo'nalishda xato qilishi mumkin: tur juda keng chiqariladi (["osh"] → string[]) yoki noto'g'ri argumentdan chiqariladi. <const T> (TypeScript 5.0) chaqiruvchidan as const talab qilmasdan literal turlarni saqlaydi. NoInfer<T> (TypeScript 5.4) esa "bu parametrdan T ni chiqarma, faqat tekshir" deydi. Va eng muhim qoida: tur parametri kamida ikki joyni bog'lamasa — u keraksiz.

Bu darsda

  • const tur parametri bilan literal va tuple turlarni avtomatik saqlaysiz.
  • NoInfer<T> bilan inference qaysi argumentdan bo'lishini boshqarasiz.
  • Tur argumentlarini qisman berib bo'lmasligini (TS2558) bilasiz.
  • Keraksiz generic'ni taniysiz: "tur parametri ikki marta uchrasin" qoidasi.
  • @ts-expect-error bilan turlarning o'zini test qilasiz.

Oldin bilishingiz kerak: Generic interface, type va klass, Generic cheklovlar va keyof, Massiv va tuple turlari (as const), Union va literal turlar.

1. Nega bu kerak?

O'tgan darslarda generic funksiyalar, turlar va klasslar yozdik. Bu dars — "ishlaydi" dan "yaxshi ishlaydi" ga o'tish. Ilg'or loyihalar va kutubxonalar kodida siz aynan shu darsdagi texnikalarni ko'rasiz.

Sardor porsiya o'lchamlari uchun yordamchi yozdi: ro'yxat beriladi, funksiya ro'yxatni va "bu qiymat ro'yxatdami?" tekshiruvini qaytaradi.

ts
function defineOptions<T extends readonly string[]>(list: T) {
  return { list };
}

const sizes = defineOptions(["kichik", "o'rta", "katta"]);
type Size = (typeof sizes.list)[number];
const wrong: Size = "XL";
console.log(wrong); // XL

tsc — xatosiz. Lekin Size — string: "XL" ham o'tib ketdi. Sababi — inference massivni string[] deb kengaytirdi (Tur chiqarish darsidagi qoida). Tuzatish — chaqiruvda as const yozish: defineOptions(["kichik", …] as const). Lekin buni har chaqiruvchi eslashi kerak. Bitta joyda unutildi — himoya yo'q. Funksiya o'zi "menga aniq qiymatlar kerak" deya olishi kerak.

2. const tur parametri

2.1 Yozuv

TypeScript 5.0 (2023-yil mart) da tur parametri oldiga const qo'yish imkoni qo'shildi:

ts
function defineOptions<const T extends readonly string[]>(list: T) {
  return { list };
}

const sizes = defineOptions(["kichik", "o'rta", "katta"]);
type Size = (typeof sizes.list)[number];
const ok: Size = "o'rta";
console.log(ok); // o'rta

Endi sizes.list turi — readonly ["kichik", "o'rta", "katta"], Size esa — "kichik" | "o'rta" | "katta". Chaqiruvchi as const yozmadi, lekin natija xuddi yozgandek. <const T> — "bu parametrga berilgan literal qiymatni as const bilan berilgandek chiqar".

Endi "XL" ushlanadi:

ts
function defineOptions<const T extends readonly string[]>(list: T) {
  return { list };
}
const sizes = defineOptions(["kichik", "o'rta", "katta"]);
type Size = (typeof sizes.list)[number];
const wrong: Size = "XL";

Kompilyator:

text
TS2322: Type '"XL"' is not assignable to type '"katta" | "kichik" | "o'rta"'.

Tarjimasi: ""XL" turini "katta" | "kichik" | "o'rta" turiga berib bo'lmaydi". Ya'ni: "Size faqat shu uch o'lcham, XL ular orasida yo'q". Xabardagi union a'zolari alifbo tartibida — tsc 7 union'larni shunday chiqaradi. Siz yozgan tartib ham, bu tartib ham — bitta tur: union'da tartib ahamiyatsiz.

2.2 Uchta variant yonma-yon

Funksiya f(["osh", "manti"]) natijasi
<T extends readonly string[]> string[]
<const T extends readonly string[]> readonly ["osh", "manti"]
<const T extends string[]> ["osh", "manti"]

Hover turlari tsc --declaration bilan tekshirilgan. Cheklovda readonly bo'lsa, natija ham readonly tuple bo'ladi — xuddi as const dagidek. Cheklov o'zgaruvchan massiv bo'lsa ham literallar saqlanadi, faqat readonly siz. Ko'pincha birinchisi kerak: ro'yxatni funksiya o'zgartirmaydi.

2.3 Obyektlarda ham ishlaydi

const tur parametri ichma-ich obyektlarni ham qotiradi:

ts
function defineDish<const T>(dish: T): T {
  return dish;
}

const osh = defineDish({ name: "Osh", sizes: ["S", "L"] });
console.log(osh.name, osh.sizes.length); // Osh 2

Hover'da osh — { readonly name: "Osh"; readonly sizes: readonly ["S", "L"] }. Har qiymat literal, hammasi readonly.

const tur parametri va as const — qarindosh, lekin farqi bor. as const qiymat yoniga yoziladi va chaqiruvchining ishi. <const T> esa funksiya imzosida turadi va funksiya muallifining qarori. Kutubxona yozayotgan bo'lsangiz, ikkinchisi foydalanuvchini bir qadamdan ozod qiladi. Natija turi esa ikkala holatda ham bir xil.

Muhim chegara: const faqat chaqiruvda to'g'ridan-to'g'ri yozilgan literalga ta'sir qiladi. Oldin o'zgaruvchiga olingan massiv (const list = ["S", "L"]; defineDish(list)) allaqachon string[] — uni orqaga qaytarib bo'lmaydi.

Tekshirib ko'ring: const names = ["Malika", "Bobur"]; const opts = defineOptions(names); — const T bo'lsa ham opts.list turi qanday?

Javob

string[]. names e'lon qilingan paytda string[] deb chiqarilgan edi. const tur parametri faqat chaqiruvning o'zida yozilgan literalni ko'radi. Literallar kerak bo'lsa — ro'yxatni chaqiruvga to'g'ridan-to'g'ri yozing yoki names ni as const qiling.

3. NoInfer<T>: "bu yerdan chiqarma"

3.1 Muammo: noto'g'ri argument T ni kengaytiradi

Endi tanlov funksiyasi: ruxsat etilgan qiymatlar, foydalanuvchi kiritgani va standart qiymat. Kiritilgan qiymat ro'yxatda bo'lmasa — standart qaytsin:

ts
function choose<T extends string>(
  allowed: readonly T[],
  value: string,
  fallback: T,
): T {
  return allowed.find((a) => a === value) ?? fallback;
}

const drink = choose(["choy", "kofe"], "kakao", "sharbat");
console.log(drink); // sharbat

tsc — xatosiz. Lekin "sharbat" ruxsat etilgan ro'yxatda yo'q-ku! Nima bo'ldi? TypeScript T ni hamma argumentlardan chiqardi: allowed dan "choy" | "kofe", fallback dan esa "sharbat". Natija: T = "choy" | "kofe" | "sharbat". Standart qiymat o'zi ruxsat ro'yxatini kengaytirib yubordi. Ikki holatni qadamma-qadam solishtiring:

Qadam fallback: T fallback: NoInfer<T>
1. allowed dan nomzod "choy" | "kofe" "choy" | "kofe"
2. fallback dan nomzod "sharbat" olinmaydi
3. Yakuniy T "choy" | "kofe" | "sharbat" "choy" | "kofe"
4. "sharbat" tekshiruvi o'tdi (u T ning o'zida) TS2345

Chap ustun — muammo, o'ng ustun — keyingi bo'limdagi yechim.

3.2 Yechim: NoInfer

TypeScript 5.4 (2024-yil mart) dagi NoInfer<T> — "bu o'rinda T ni chiqarishda qatnashma, faqat tekshir":

ts
function choose<T extends string>(
  allowed: readonly T[],
  value: string,
  fallback: NoInfer<T>,
): T {
  return allowed.find((a) => a === value) ?? fallback;
}
const drink = choose(["choy", "kofe"], "kakao", "sharbat");

Kompilyator:

text
TS2345: Argument of type '"sharbat"' is not assignable to parameter of type '"choy" | "kofe"'.

Tarjimasi: ""sharbat" turidagi argumentni "choy" | "kofe" turidagi parametrga berib bo'lmaydi". Endi T faqat allowed dan chiqarildi: "choy" | "kofe". fallback esa shu tur bilan tekshirildi va "sharbat" rad etildi. Xabardagi union tartibi siz yozgandan farq qilishi mumkin — tsc 7 union a'zolarini o'z tartibida chiqaradi, ma'nosi bir xil.

NoInfer — tayyor tur (Array, Record kabi), import kerak emas. JavaScript'da u ham iz qoldirmaydi.

3.3 Qayerda ishlatiladi?

Qoida oddiy: asosiy manba bitta parametr, qolganlari esa unga mos kelishi kerak bo'lsa — qolganlarini NoInfer ga o'rang. Odatiy holatlar:

  • standart qiymat (fallback, defaultValue);
  • ro'yxatdan tanlangan boshlang'ich holat (initial);
  • "faqat shu kalitlardan biri" degan qo'shimcha parametr.

Tekshirib ko'ring: choose(["choy", "kofe"], "kakao", "kofe") — NoInfer bilan xato bormi? Natija nima?

Javob

Xato yo'q: "kofe" ro'yxatda bor. "kakao" ro'yxatda yo'q, shuning uchun natija — standart qiymat "kofe". Ikkinchi parametr — string, uni tekshirish ishlash paytida, find bilan.

4. Tur argumentlarini boshqarish

4.1 Hammasi yoki hech biri

Tur argumentlarini o'zingiz yozsangiz — hammasini yozish kerak (standart qiymatli bo'lmasa):

ts
function pair<A, B>(a: A, b: B): [A, B] {
  return [a, b];
}
pair<string>("Osh", 35000);

Kompilyator:

text
TS2558: Expected 2 type arguments, but got 1.

Tarjimasi: "2 ta tur argumenti kutilgan edi, 1 ta berildi". TypeScript'da "birinchisini men aytaman, ikkinchisini o'zing chiqar" (qisman inference) yo'q. Yo hammasi chiqariladi, yo hammasi yoziladi. Chiqish yo'li — standart tur parametri (<A, B = unknown>) yoki funksiyani ikkiga bo'lish.

4.2 Qachon tur argumentini yozish kerak?

Holat Misol
Argumentlardan chiqarib bo'lmaydi new Map<string, number>(), emptyList<Order>()
Chiqarilgan tur juda tor useState<Order | null>(null)
Chiqarilgan tur juda keng pair<string | number>(…)
Qolgan hollarda yozmang — inference to'g'ri

Ikkinchi qator React'dan (17-qism): null dan T = null chiqariladi, keyin buyurtmani yozib bo'lmaydi. Tur argumenti "aslida bu yerga Order ham keladi" deydi.

5. Keraksiz generic

5.1 Oltin qoida: tur parametri ikki marta uchrasin

TypeScript hujjatlaridagi generic yozish qoidalaridan eng muhimi: tur parametri kamida ikki joyda uchrashi kerak. Generic — bog'lanish. Bitta joydagi T hech narsani hech narsaga bog'lamaydi:

ts
// ❌ T bitta joyda — generic hech narsa bermaydi
function greet<S extends string>(name: S): string {
  return `Xush kelibsiz, ${name}!`;
}

// ✅ oddiy tur yetarli
function greetPlain(name: string): string {
  return `Xush kelibsiz, ${name}!`;
}

console.log(greet("Malika") === greetPlain("Malika")); // true

Ikkala funksiya bir xil qabul qiladi va bir xil qaytaradi. S faqat o'qishni qiyinlashtirdi. Natija turida S bo'lganda edi (masalan, `Xush kelibsiz, ${S}!` turi), u o'z o'rnida bo'lardi — bu Template literal types darsida.

5.2 Tur parametrini "pastga" tushiring

Ikki imzo — bir xil ish:

ts
function first1<T>(items: readonly T[]): T | undefined {
  return items[0];
}
function first2<A extends readonly unknown[]>(items: A): A[number] {
  return items[0];
}

const a = first1([1, 2, 3]);
const b = first2([1, 2, 3]);
console.log(a, b); // 1 1

Natija turlarini solishtiring: a — number | undefined, b — number. Ikkinchisi undefined ni yo'qotdi: A[number] — "massiv elementi", bo'sh massivda esa element yo'q. Bundan tashqari, first2 imzosini o'qish qiyin. Handbook qoidasi: tur parametrini eng kichik birlikka qo'ying — butun massivga emas, elementga (T[] dagi T).

5.3 Ortiqcha tur parametri

ts
// ❌ F — keraksiz: u faqat bitta joyda
function keep<T, F extends (item: T) => boolean>(
  items: T[],
  test: F,
): T[];
// ✅
function keep<T>(items: T[], test: (item: T) => boolean): T[];

F bitta joyda uchraydi — demak keraksiz. Kamroq tur parametri — sodda imzo, aniqroq xato xabarlari.

Bunday joylarni avtomatik topadigan qoida ham bor: typescript-eslint'dagi no-unnecessary-type-parameters ("keraksiz tur parametrlari yo'q"). U "faqat bir marta ishlatilgan" tur parametrlarini ko'rsatadi.

5.4 Yaxshi generic: tekshiruv ro'yxati

flowchart TD
  A["Tur parametri<br/>kerakmi?"] --> B{"T 2 joyni<br/>bog'laydimi?"}
  B -- "yo'q" --> C["Oddiy tur yoki unknown"]
  B -- "ha" --> D{"T faqat natijadami?"}
  D -- "ha" --> E["Yo'q: bu yashirin as<br/>(parse&lt;T&gt;)"]
  D -- "yo'q" --> F["Generic — to'g'ri tanlov"]
  F --> G["T ni eng kichik<br/>birlikka qo'ying"]

Bu sxema Generics darsidagi "yolg'onchi generic" (parse<T>) qoidasini ham o'z ichiga oladi: natijadagi T hech qaysi parametrda bo'lmasa, u tekshiruv emas, va'da.

5.5 O'qiluvchanlik ham o'lchov

Generic imzo — funksiyaning hujjati. Uni boshqa dasturchi hover'da o'qiydi, xato xabarida ko'radi. Ikki imzoni solishtiring:

ts
function a<T>(
  items: readonly T[],
  key: (item: T) => string,
): Map<string, T[]>;

function b<T, K extends string, F extends (x: T) => K>(
  items: readonly T[],
  key: F,
): Map<K, T[]>;

Ikkinchisi "aqlliroq": kalitlarni literal turda saqlaydi. Lekin hover'da u ancha uzun, xato bo'lsa — xabar ham uch barobar uzun bo'ladi. Murakkab tur faqat foydasi aniq bo'lganda o'zini oqlaydi. Amaliy qoida: avval eng sodda imzoni yozing; chaqiruvchida haqiqiy muammo chiqqandagina (masalan, kalit turi kerak bo'lsa) murakkablashtiring.

Tekshirib ko'ring: function toArray<T>(value: T): T[] — tur parametri nechta joyda uchraydi va u kerakmi?

Javob

Ikki joyda: parametrda (value: T) va natijada (T[]). U kirish va chiqishni bog'laydi: toArray(35000) — number[], toArray("Osh") — string[]. Demak generic to'g'ri. unknown bilan yozilganda natija unknown[] bo'lib, tur yo'qolardi.

6. Turlarni test qilish: @ts-expect-error

Generic'lar yozganda "bu chaqiruv xato berishi kerak" degan talab ham test qilinishi kerak. Masalan, choose ga ro'yxatda yo'q standart qiymat berilsa, tsc to'xtatishi kerak. Buning uchun maxsus izoh bor:

ts
function choose<T extends string>(
  allowed: readonly T[],
  value: string,
  fallback: NoInfer<T>,
): T {
  return allowed.find((a) => a === value) ?? fallback;
}

// @ts-expect-error — "sharbat" ro'yxatda yo'q
choose(["choy", "kofe"], "kakao", "sharbat");
console.log(choose(["choy", "kofe"], "kakao", "choy")); // choy

// @ts-expect-error — "keyingi qatorda tur xatosi bo'lishi kerak". Xato bo'lsa — tsc jim (blok tekshiruvdan o'tdi). Xato bo'lmasa — tsc o'zi xato beradi: TS2578: Unused '@ts-expect-error' directive. Ya'ni bu — tur darajasidagi test: kimdir NoInfer ni olib tashlasa, tsc darhol aytadi. Buni 3-mashqda ishlatasiz.

Uning qardoshi @ts-ignore esa xato bormi-yo'qmi — jim turadi. Shuning uchun u xavfli va kam ishlatiladi (TypeScript best practices darsida).

@ts-expect-error dan keyin izoh yozish odat: nega xato kutilmoqda (— "sharbat" ro'yxatda yo'q). Uch oydan keyin bu qatorni o'qigan dasturchi uni "eski, keraksiz" deb o'chirib yubormasligi uchun.

Tekshirib ko'ring: Kimdir choose dan NoInfer ni olib tashladi. Testdagi @ts-expect-error qatorida nima bo'ladi?

Javob

tsc TS2578: Unused '@ts-expect-error' directive. beradi. NoInfer siz "sharbat" T ni kengaytiradi va xato yo'qoladi — "kutilgan xato" chiqmagani esa o'zi xato. Tur testi o'zgarishni darhol ushladi.

7. TypeScript ushlamaydigan tuzoq: Node tur xatosini bilmaydi

Yuqoridagi blokda @ts-expect-error qatori bajarildi — choose chaqirildi va "sharbat" qaytdi. Node turlarni tekshirmaydi, faqat o'chiradi (TypeScript'ni o'rnatish darsi). Xuddi shu holat @ts-expect-error siz ham bo'ladi:

ts
function choose<T extends string>(
  allowed: readonly T[],
  value: string,
  fallback: NoInfer<T>,
): T {
  return allowed.find((a) => a === value) ?? fallback;
}
const drink = choose(["choy", "kofe"], "kakao", "sharbat");
console.log(drink);

Kompilyator:

text
TS2345: Argument of type '"sharbat"' is not assignable to parameter of type '"choy" | "kofe"'.

Lekin node drink.ts bu faylni jim bajaradi:

text
sharbat

Mashqlardagi testlar ham shunday: node --test tur xatoli faylni ham ishga tushiradi va testlar "o'tishi" mumkin. Qoida: testdan oldin har doim npx tsc --noEmit (yoki npm run tip). vazifalar da npm test va npm run tip aynan shuning uchun alohida qadamlar, CI'da esa ikkalasi ham ishlaydi.

8. Ko'p uchraydigan xatolar

8.1 Chaqiruvchidan as const kutish

Funksiya literal turga tayanadi, lekin chaqiruvchi as const ni unutadi — tur string[] ga kengayadi. Tuzatish: <const T extends readonly …>.

8.2 Standart qiymat T ni kengaytiradi

fallback: T — noto'g'ri standart qiymat ruxsat ro'yxatiga qo'shilib ketadi. Tuzatish: fallback: NoInfer<T>.

8.3 Tur argumentlarini qisman berish

pair<string>(…) — TS2558. Tuzatish: hammasini yozing yoki standart tur parametri qo'shing.

8.4 Bitta joydagi tur parametri

greet<S extends string>(name: S): string — keraksiz. Tuzatish: name: string.

8.5 Node "o'tdi" — demak tur to'g'ri deb o'ylash

Node turlarni tekshirmaydi. Tuzatish: tsc --noEmit testdan oldin.

9. Mashqlar

1-mashq (oson): Natija turlari

ts
function plain<T extends readonly string[]>(items: T): T {
  return items;
}
function frozen<const T extends readonly string[]>(items: T): T {
  return items;
}
const a = plain(["S", "M"]);
const b = frozen(["S", "M"]);
console.log(a.length, b.length); // 2 2

a ning turi: [:string[]]. b[0] ning turi (literal): [:"S"]. b.length ning turi (literal son): .

Yechim
  • a — string[]: oddiy inference massivni kengaytiradi.
  • b — readonly ["S", "M"], b[0] — "S": const tur parametri literallarni saqladi.
  • b.length — 2: tuple uzunligi literal tur (Massiv va tuple turlari).

2-mashq (o'rta): Keraksiz generic'ni toping

Quyidagi uch funksiyadan qaysi birida tur parametri keraksiz? Uni oddiy turga almashtiring.

ts
function wrap<T>(value: T): { value: T } { … }
function total<P extends number>(prices: P[]): number { … }
function lastOf<T>(items: readonly T[]): T | undefined { … }
Yechim

total da: P faqat parametrda, natija esa oddiy number. Yig'indi P ga bog'liq emas.

ts
function total(prices: readonly number[]): number {
  return prices.reduce((sum, p) => sum + p, 0);
}
console.log(total([35000, 5000])); // 40000

wrap va lastOf da T ikki joyda — parametr va natijani bog'laydi. Ular to'g'ri generic.

3-mashq (qiyin): Amaliy tajriba — variantlar ro'yxati

Mashq kurs/mashqlar/15/ papkasida. 23-ilgor/options.ts:

  • defineOptions(list) — { list, has(value) } qaytarsin; has — tur predikati (value is …): satr ro'yxatdagi qiymatlardan birimi?
  • choose(allowed, value, fallback) — value ro'yxatda bo'lsa o'zi, bo'lmasa fallback. fallback ham ro'yxatdan bo'lishi shart.

Avval const va NoInfer siz yozing. Testda tur talablarini @ts-expect-error bilan tekshiring: const wrong: Size = "XL" va choose(SIZES.list, "XL", "ulkan") — ikkalasi ham tur xatosi bo'lishi kerak. npx tsc --pretty false nima deydi? Keyin const va NoInfer qo'shing.

Yechim

Birinchi variantda tsc 7.0.2:

text
23-ilgor/options.test.ts(13,3): error TS2578: Unused '@ts-expect-error' directive.
23-ilgor/options.test.ts(24,3): error TS2578: Unused '@ts-expect-error' directive.

"Ishlatilmagan @ts-expect-error" — ya'ni kutilgan xatolar chiqmadi: Size — string, "ulkan" esa T ni kengaytirdi. Tur testlari ikkala zaiflikni ham ushladi.

ts
// 23-ilgor/options.ts — variantlar ro'yxati va xavfsiz tanlov
export function defineOptions<const T extends readonly string[]>(
  list: T,
) {
  return {
    list,
    // Tur predikati: satr ro'yxatdagi qiymatlardan birimi?
    has(value: string): value is T[number] {
      return list.includes(value);
    },
  };
}

// value ro'yxatda bo'lsa — o'zi, bo'lmasa — fallback.
// NoInfer: fallback T ni kengaytirmaydi, ro'yxatdan bo'lishi shart
export function choose<T extends string>(
  allowed: readonly T[],
  value: string,
  fallback: NoInfer<T>,
): T {
  return allowed.find((a) => a === value) ?? fallback;
}
ts
// 23-ilgor/options.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import { defineOptions, choose } from "./options.ts";

const SIZES = defineOptions(["kichik", "o'rta", "katta"]);
type Size = (typeof SIZES.list)[number];

test("defineOptions: ro'yxat va tekshiruv", () => {
  const size: Size = "o'rta";
  assert.equal(SIZES.has(size), true);
  assert.equal(SIZES.has("XL"), false);
  // @ts-expect-error — "XL" o'lchamlar ro'yxatida yo'q
  const wrong: Size = "XL";
  assert.equal(SIZES.has(wrong), false);
});

test("choose: ruxsat etilgan yoki standart", () => {
  assert.equal(choose(SIZES.list, "katta", "o'rta"), "katta");
  assert.equal(choose(SIZES.list, "XL", "o'rta"), "o'rta");
});

test("choose: standart qiymat ham ro'yxatdan bo'lsin", () => {
  // @ts-expect-error — "ulkan" ro'yxatda yo'q
  const size = choose(SIZES.list, "XL", "ulkan");
  assert.equal(size, "ulkan");
});
  • value is T[number] — T[number] — tuple elementlari union'i (keyof, typeof va indexed access darsida). has("o'rta") dan keyin TypeScript satrni Size deb biladi.
  • Uchinchi testdagi assert.equal(size, "ulkan") ataylab: «Node tur xatosini bilmaydi» bo'limidagi holat. Tur xatosi bor qator ham bajariladi — @ts-expect-error uni faqat tsc uchun "kutilgan" deb belgilaydi.

npx tsc --pretty false — chiqishsiz. node --test 23-ilgor/options.test.ts bizda (Node 24.21.0) shunday chiqdi:

text
✔ defineOptions: ro'yxat va tekshiruv (0.9726ms)
✔ choose: ruxsat etilgan yoki standart (0.1954ms)
✔ choose: standart qiymat ham ro'yxatdan bo'lsin (0.1742ms)
ℹ tests 3
ℹ suites 0
ℹ pass 3
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 158.3124

E'tibor bering: birinchi (zaif) variantda ham node --test uchala testdan o'tardi — tur zaifligini faqat tsc ko'rdi. XATOLAR.md ga qo'shing: TS2558, TS2578, NoInfer dagi TS2345. Keyin kurs/mashqlar papkasidan:

bash
git add 15/23-ilgor 15/XATOLAR.md
git commit -m "15/23: options.ts — const tur parametri va NoInfer"

10. Real ishda

  • Kutubxona API'lari: marshrutlar, holat mashinalari, forma sxemalari kabi kutubxonalar const tur parametri bilan foydalanuvchi yozgan nomlarni ("/menu", "tayyor") aniq turga aylantiradi. Ilgari ular hujjatda "as const yozing" deb so'rardi.
  • NoInfer — "standart qiymat", "boshlang'ich holat" parametrlarida: kutubxona mualliflari uchun kichik, lekin qimmatli vosita.
  • Tur testlari: kutubxonalarda @ts-expect-error bilan to'la *.test-d.ts fayllar bor — ular API turlarining o'zini himoya qiladi.
  • Kod ko'rib chiqishda "bu tur parametri bir marta ishlatilgan" — tez-tez yoziladigan izoh.
  • Intervyu: "const tur parametri as const dan nimasi bilan farq qiladi?", "NoInfer nimaga kerak?", "Generic qachon keraksiz?" — middle/senior savollari.

Xulosa

  • <const T> — chaqiruvdagi literalni as const bilan berilgandek chiqaradi; readonly cheklov bilan — readonly tuple. Faqat to'g'ridan-to'g'ri yozilgan literalga ta'sir qiladi.
  • NoInfer<T> — shu parametr T ni chiqarishda qatnashmaydi, faqat tekshiriladi. Standart qiymatlar uchun.
  • Tur argumentlari — hammasi yoki hech biri (TS2558); qisman inference yo'q.
  • Tur parametri kamida ikki joyni bog'lasin, eng kichik birlikka qo'yilsin; natijadagina bo'lsa — bu yashirin as.
  • @ts-expect-error — tur testi. Node turlarni tekshirmaydi: testdan oldin tsc --noEmit.

Keyingi dars: Function overload va this turi — bitta funksiya turli kirishga turli natija turi qaytarishi kerak bo'lsa.

Manbalar

  • TypeScript 5.0 Release Notes: "const Type Parameters" — typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html
  • TypeScript 5.4 Release Notes: "Preserved Narrowing… / The NoInfer Utility Type" — typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html
  • TypeScript Handbook: "More on Functions" (Guidelines for Writing Good Generic Functions) — typescriptlang.org/docs/handbook/2/functions.html
  • typescript-eslint: no-unnecessary-type-parameters — typescript-eslint.io/rules/no-unnecessary-type-parameters
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
TypeScript generics amaliyoti: const tur parametri, NoInfer va keraksiz generic — IlmHamroh