Texnik intervyu: TypeScript
Full-stack dasturchi uchun chuqur TypeScript intervyu to'plami. Klassik savollardan tortib tuzoq (trap) savollargacha. Har bir javob quyidagi tuzilishda: Ta'rif Mexanizm Kod misol Keng tarqalgan xato Follow-up.
Qanday foydalanish
- Savolni o'qib, avval o'zingiz javob berishga urining, keyin javobni ko'ring.
- Belgilar: Junior · Middle · Senior darajadagi savol.
- Intervyuda muhimi — tushunib gapirish. Yodlash emas, mexanizmni tushuntira olish.
- Inglizcha atamalar (
type,narrowing,structural typing) va kod ataylab saqlangan — intervyuda ular shu holicha ishlatiladi.
TypeScript — bu "tiplashtirilgan JavaScript" emas, balki kod haqida fikrlash tili. Compile paytida ishlaydigan, runtime'da yo'q bo'ladigan qatlam.
1. Asoslar
S: TypeScript nima va nega JavaScript ustidan qo'shimcha qatlam kerak? (Junior)
Ta'rif. TypeScript — JavaScript'ning statik tiplashtirilgan superseti (ustki to'plami). Har qanday to'g'ri JS kodi — to'g'ri TS kodi hamdir, lekin TS qo'shimcha ravishda tip tizimi (type system) beradi.
Mexanizm. TS kodi to'g'ridan-to'g'ri ishlamaydi — tsc (compiler) uni oddiy JS'ga transpile qiladi. Tiplar faqat compile paytida yashaydi va yakuniy JS'da butunlay yo'qoladi (type erasure). Ya'ni TS runtime'ga hech qanday qo'shimcha yuk qo'ymaydi — u faqat yozish va compile bosqichida ishlaydi.
Kod misol.
// TypeScript
function salomlash(ism: string): string {
return `Salom, ${ism}`;
}
salomlash(42); // Compile xatosi: number string'ga mos emas
// Compile qilingandan keyingi JS (tiplar yo'q):
function salomlash(ism) {
return `Salom, ${ism}`;
} Keng tarqalgan xato. "TS kodni runtime'da tekshiradi" deb o'ylash. Yo'q — agar API'dan noto'g'ri tipdagi ma'lumot kelsa, TS uni ushlamaydi, chunki tiplar runtime'da mavjud emas. Runtime tekshiruvi uchun zod kabi kutubxonalar yoki qo'lda validatsiya kerak.
Follow-up. "Agar tiplar runtime'da yo'q bo'lsa, enum va class nega yakuniy JS'da qoladi?" — Chunki ular faqat tip emas, balki qiymat (value) ham yaratadi. interface esa toza tip — u to'liq o'chib ketadi.
S: interface va type o'rtasidagi farq nima? Qachon qaysini tanlaysiz? (Junior)
Ta'rif. Ikkalasi ham nomlangan tip e'lon qiladi, lekin imkoniyatlari va xatti-harakati farq qiladi.
Mexanizm.
interface— asosan obyekt shakli (object shape) uchun. Extends qilinadi va declaration merging (bir nomdagi ikki interface avtomatik birlashadi) qo'llab-quvvatlanadi.type— alias (taxallus). Union, intersection, primitiv, tuple, mapped/conditional tiplar uchun ishlaydi. Merging yo'q — ikki marta e'lon qilsangiz xato beradi.
Kod misol.
// interface — kengaytiriladi va birlashadi
interface Foydalanuvchi {
ism: string;
}
interface Foydalanuvchi {
yosh: number; // avtomatik birlashadi (declaration merging)
}
// Endi Foydalanuvchi = { ism: string; yosh: number }
// type — union, intersection uchun kuchli
type Holat = "yuklanmoqda" | "tayyor" | "xato"; // union — interface qila olmaydi
type ID = string | number;
type Toʻliq = Foydalanuvchi & { email: string }; // intersection Keng tarqalgan xato. Kutubxona (library) uchun ochiq API'da type ishlatish. Interface'ni foydalanuvchi declaration merging orqali kengaytira oladi, type esa yopiq. Umumiy qoida: obyekt shakli uchun interface, boshqa hamma narsa (union, tuple, primitiv, mapped) uchun type.
Follow-up. "type bilan extends qilib bo'ladimi?" — To'g'ridan-to'g'ri emas, lekin intersection orqali: type B = A & { yangi: number }. Ammo bu declaration merging emas — ikki xil mexanizm.
S: Structural typing (strukturaviy tiplash) nima? U nominal typing'dan qanday farq qiladi? (Middle)
Ta'rif. TS strukturaga qarab tiplarni taqqoslaydi — nomiga emas. Ya'ni "agar ikki obyekt bir xil shaklga ega bo'lsa, ular mos keladi", nomlari boshqa bo'lsa ham. Bu ko'pincha duck typing deb ham ataladi.
Mexanizm. Java/C# kabi tillar nominal (nomga asoslangan): tip mosligi uchun aynan o'sha class/interface nomi kerak. TS esa strukturaviy: kompilyator faqat maydonlar (property) va ularning tiplarini solishtiradi.
Kod misol.
interface Nuqta {
x: number;
y: number;
}
class Koordinata {
constructor(public x: number, public y: number) {}
}
function chizish(n: Nuqta) { /* ... */ }
chizish(new Koordinata(1, 2)); // Ishlaydi! Koordinata "Nuqta"ni implement qilmagan,
// lekin shakli mos keladi
chizish({ x: 1, y: 2, z: 3 }); // Object literal bo'lsa "excess property" xato beradi Keng tarqalgan xato. Ikki mantiqan boshqa, lekin bir xil shakldagi tipni (masalan UserId va PostId, ikkalasi string) TS ajratmaydi — ularni almashtirib yuborsangiz xato bermaydi. Yechim — branded/nominal types (type UserId = string & { __brand: "user" }).
Follow-up. "Nega object literal berilganda "excess property" xatosi chiqadi, lekin o'zgaruvchi orqali berilganda chiqmaydi?" — TS yangi yaratilgan literal uchun qat'iyroq tekshiruv qiladi (typo'larni ushlash uchun); o'zgaruvchi orqali berilganda faqat strukturaviy moslik tekshiriladi.
2. Tip tizimi asoslari
S: Primitive, union va intersection tiplarni tushuntiring. (Junior)
Ta'rif. Primitive — TS'ning asosiy qurilish bloklari (string, number, boolean, null, undefined, symbol, bigint). Union (A | B) — "A yoki B". Intersection (A & B) — "A ** va** B (ikkalasi birga)".
Mexanizm. Union tipdagi qiymat ikkala tipdan birini qabul qiladi — lekin foydalanishdan oldin qaysi biri ekanligini aniqlash (narrowing) kerak. Intersection esa ikki tipni birlashtiradi — natijaviy obyekt ikkala tipning barcha maydonlariga ega bo'lishi shart.
Kod misol.
type ID = string | number; // union: yo string, yo number
let x: ID = "abc"; //
x = 123; //
type A = { ism: string };
type B = { yosh: number };
type AB = A & B; // intersection: ikkalasi ham bo'lishi shart
const odam: AB = { ism: "Ali", yosh: 30 }; // ikkala maydon majburiy Keng tarqalgan xato. Union'da to'g'ridan-to'g'ri faqat bitta tipga xos metodni chaqirish: function f(x: string | number) { return x.toUpperCase() } — numberda toUpperCase yo'q. Avval typeof x === "string" bilan narrow qilish kerak.
Follow-up. "Primitivlar intersection'i nima beradi? type X = string & number?" — never, chunki hech bir qiymat bir vaqtda ham string, ham number bo'la olmaydi.
S: Literal types va as const nima? Ular birga qanday ishlaydi? (Middle)
Ta'rif. Literal type — aniq bitta qiymatni tip sifatida ishlatish: "tayyor", 42, true. as const — TS'ga "bu qiymatni maksimal tor (narrow) va readonly tarzda tiplashtir" deb aytadi.
Mexanizm. Odatda TS const x = "tayyor" uchun "tayyor" literal tipni beradi, lekin let x = "tayyor" uchun kengaytirib (widening) string qiladi. as const esa butun obyekt/massivni chuqur readonly va literal qiladi.
Kod misol.
let holat = "tayyor"; // tip: string (widened)
const holat2 = "tayyor"; // tip: "tayyor" (literal)
const konfig = {
metod: "GET",
qayta: 3,
} as const;
// tip: { readonly metod: "GET"; readonly qayta: 3 }
const ranglar = ["qizil", "yashil"] as const;
// tip: readonly ["qizil", "yashil"] (tuple, o'zgarmas)
type Rang = typeof ranglar[number]; // "qizil" | "yashil" Keng tarqalgan xato. as constsiz massivdan union chiqarmoqchi bo'lish. const r = ["a", "b"] string[], typeof r[number] string. as const bo'lmasa literal union chiqmaydi.
Follow-up. "Funksiyaga metod: "GET" beryapman, lekin string deb xato beryapti — nega?" — Obyekt literal let-kabi widen bo'lgan (metod: string). Yechim — as const yoki tipni aniq belgilash.
S: enum nima? const enum va oddiy enum farqi nimada? Nega ba'zilar enumdan qochadi? (Middle)
Ta'rif. enum — nomlangan konstantalar to'plami. const enum — compile paytida to'liq inline qilinadigan, runtime'da obyekt qoldirmaydigan versiya.
Mexanizm. Oddiy enum yakuniy JS'da haqiqiy obyekt yaratadi (ikki tomonlama xarita: nomqiymat va qiymatnom). const enum esa hech qanday obyekt yaratmaydi — har bir foydalanish joyiga qiymat to'g'ridan-to'g'ri qo'yiladi (inline).
Kod misol.
enum Yonalish { Yuqori, Past } // runtime'da obyekt qoladi
let d = Yonalish.Yuqori; // let d = Yonalish.Yuqori (0)
const enum Rang { Qizil, Yashil } // inline bo'ladi
let r = Rang.Qizil; // let r = 0 (Rang obyekti umuman yo'q)
// Ko'p loyihalar enum o'rniga union + as const ishlatadi:
const Holat = { Faol: "faol", Nofaol: "nofaol" } as const;
type Holat = typeof Holat[keyof typeof Holat]; // "faol" | "nofaol" Keng tarqalgan xato. const enumni kutubxona chegarasi orqali ishlatish. Bir necha compile sozlamalari (isolatedModules, ba'zi bundlerlar) const enumni qo'llab-quvvatlamaydi va u buziladi. Shu sabab ko'p jamoalar umuman enumdan voz kechib, union literal + as const ishlatadi.
Follow-up. "Nega enumni ko'pchilik yomon ko'radi?" — U TS'ning "runtime'da yo'qolish" tamoyilini buzadi (JS chiqishga kod qo'shadi), tree-shaking'ni qiyinlashtiradi, va const enum bundler muammolari beradi. Union tiplar toza va yengil.
3. Generics
S: Generic nima va nima uchun kerak? Oddiy misol bilan tushuntiring. (Middle)
Ta'rif. Generic — tipni parametr sifatida qabul qilish. Ya'ni funksiya/klass/tip bir necha xil tip bilan, tip xavfsizligini yo'qotmasdan, qayta ishlatiladigan bo'ladi.
Mexanizm. Generic <T> — "chaqiruv paytida aniqlanadigan tip o'rni". TS ko'pincha uni argumentdan avtomatik chiqaradi (type inference), shuning uchun har doim qo'lda yozish shart emas.
Kod misol.
// Genericsiz: har tip uchun alohida funksiya yoki any (xavfli)
function birinchiAny(arr: any[]): any { return arr[0]; }
// Generic bilan: kirish tipi chiqish tipiga bog'lanadi
function birinchi<T>(arr: T[]): T {
return arr[0];
}
const n = birinchi([1, 2, 3]); // T = number n: number
const s = birinchi(["a", "b"]); // T = string s: string (inference) Keng tarqalgan xato. Generic'ni keraksiz joyga qo'yish yoki anyni "generic"deb atash. function f<T>(x: T): any — bu generic'ni behuda ishlatish, chunki chiqish any — tip bog'lanmagan. Generic'ning butun ma'nosi — kirish va chiqishni bog'lash.
Follow-up. "Bitta funksiyada bir nechta generic bo'la oladimi?" — Ha: function map<T, U>(arr: T[], fn: (x: T) => U): U[]. Bu yerda T — kirish, U — chiqish elementi tipi.
S: Generic constraints (extends) nima? keyof bilan qanday birga ishlatiladi? (Senior)
Ta'rif. Constraint — generic tipni cheklash: "T faqat shu shartga mos tip bo'lishi mumkin". T extends U — "T U'ning ostki tipi bo'lishi kerak" degani.
Mexanizm. Constraintsiz T — "har qanday narsa", shuning uchun uning maydonlariga murojaat qila olmaysiz. extends bilan cheklab, TS'ga T haqida ma'lum kafolat berasiz. keyof T — T'ning barcha kalitlarining union'i; u constraint bilan birga type-safe obyekt kirishini ta'minlaydi.
Kod misol.
// K, T'ning haqiqiy kaliti bo'lishini kafolatlaydi
function olish<T, K extends keyof T>(obj: T, kalit: K): T[K] {
return obj[kalit];
}
const user = { ism: "Ali", yosh: 30 };
olish(user, "ism"); // tip: string
olish(user, "yosh"); // tip: number
olish(user, "email"); // Compile xatosi: "email" kalit emas
// Constraint moslik uchun
function uzunlik<T extends { length: number }>(x: T): number {
return x.length; // .length borligiga kafolat
} Keng tarqalgan xato. T[K] return tipini any yoki Tga qo'yish. To'g'ri return tipi — T[K] (indexed access type), u aynan tanlangan maydon tipini qaytaradi. Aks holda tip aniqligi yo'qoladi.
Follow-up. "Default generic qiymat berish mumkinmi?" — Ha: interface Box<T = string> { value: T }. Boxni tipsiz ishlatilsa, T string bo'ladi.
S: Covariance va contravariance nima? Funksiya parametrlarida qanday namoyon bo'ladi? (Senior)
Ta'rif. Bu — tiplar ostki-tip (subtype) munosabatida qanday "yo'nalishda" mos kelishini bildiradi. Covariant — ostki tip o'rniga ishlatiladi (bir yo'nalish). Contravariant — teskari yo'nalish (asosan funksiya parametrlarida).
Mexanizm. Agar Dog Animalning ostki tipi bo'lsa:
- Return pozitsiyasi covariant:
() => Dog() => Animalga mos (ko'proq aniq narsa qaytarish xavfsiz). - Parameter pozitsiyasi contravariant:
(x: Animal) => void(x: Dog) => voidga mos (kengroq narsa qabul qilish xavfsiz). TS bu qoidanistrictFunctionTypesyoqilganda qo'llaydi. Ammo metod parametrlari (bivariant) tarixiy sabablarga ko'ra istisno.
Kod misol.
class Animal { nafas() {} }
class Dog extends Animal { vov() {} }
// Return covariance
type FnA = () => Animal;
const fd: FnA = (): Dog => new Dog(); // Dog Animal'ga mos (aniqroq)
// Parameter contravariance (strictFunctionTypes bilan)
type Handler = (a: Dog) => void;
const h: Handler = (a: Animal) => {}; // kengroq parametr xavfsiz
const teskari: (a: Dog) => void = (a: Animal) => a.nafas();
// — Animal qabul qiluvchi funksiya Dog kutilgan joyda ishlaydi Keng tarqalgan xato. Array'lar TS'da covariant (nazariy jihatdan noto'g'ri): Dog[]ni Animal[]ga berib, keyin unga Cat qo'shsangiz — TS ushlamaydi. Bu TS'ning ataylab qilgan amaliy (soundness'ni feda qilgan) yon berishlaridan biri.
Follow-up. "strictFunctionTypes metod parametrlariga nega ta'sir qilmaydi?" — Ular bivariant qoldirilgan, chunki juda ko'p mavjud kod (masalan, DOM event handler'lar, array metodlari) contravariant qat'iy qoidada buziladi. Bu — amaliylik uchun tip soundness'ining ataylab yumshatilishi.
4. Utility tiplar
S: Partial, Required, Readonly, Pick, Omit, Record — har birini tushuntiring. (Middle)
Ta'rif. Bular — TS ichida tayyor keladigan utility (yordamchi) tiplar. Mavjud tipdan yangi tip yaratadi.
Mexanizm. Barchasi asosan mapped type ustiga qurilgan. Partial har maydonga ? qo'shadi, Required uni olib tashlaydi, Readonly readonly qo'shadi, Pick/Omit maydonlarni tanlaydi/chiqaradi, Record kalitqiymat obyektini quradi.
Kod misol.
interface User {
id: number;
ism: string;
email?: string;
}
type A = Partial<User>; // barcha maydon ixtiyoriy: { id?; ism?; email? }
type B = Required<User>; // barcha maydon majburiy: { id; ism; email }
type C = Readonly<User>; // { readonly id; readonly ism; ... }
type D = Pick<User, "id" | "ism">; // { id: number; ism: string }
type E = Omit<User, "email">; // { id: number; ism: string }
type F = Record<string, number>; // { [kalit: string]: number }
// Amaliy: yangilash funksiyasi faqat qism maydon oladi
function yangilash(id: number, ozgarishlar: Partial<User>) { /* ... */ } Keng tarqalgan xato. Omitni noto'g'ri kalit bilan ishlatish TS3.5'gacha xato bermasdi — endi beradi, lekin Omit<T, "notaknit"> ba'zan sokin o'tib ketishi mumkin. Har doim kalitlar to'g'riligini tekshiring. Yana — Partialni chuqur (nested) deb o'ylash: u faqat birinchi qatlamni ixtiyoriy qiladi, ichki obyektlarga tegmaydi.
Follow-up. "ReturnType va Parameters nima qiladi?" — ReturnType<typeof fn> funksiya qaytaradigan tipni, Parameters<typeof fn> esa uning argumentlarini tuple sifatida chiqaradi. Ikkalasi ham ichida inferdan foydalanadi.
S: ReturnType va Parameters ichkarida qanday ishlaydi? infer bu yerda qanday rol o'ynaydi? (Senior)
Ta'rif. ReturnType<T> — funksiya tipidan uning natija tipini, Parameters<T> — argumentlar tuple'ini ajratib oladi. Ikkalasi ham conditional type + infer ustiga qurilgan.
Mexanizm. infer — conditional type ichida "shu joydagi tipni ushlab, o'zgaruvchiga yoz" degani. TS namunaga (pattern) moslashtirib, kerakli qismni chiqaradi.
Kod misol.
// Standart kutubxonadagi haqiqiy ta'rif:
type ReturnType<T extends (...args: any) => any> =
T extends (...args: any) => infer R ? R : never;
// natija tipini "R"ga ushlaydi
type Parameters<T extends (...args: any) => any> =
T extends (...args: infer P) => any ? P : never;
// argumentlarni "P" tuple'ga ushlaydi
function foo(a: string, b: number): boolean { return true; }
type R = ReturnType<typeof foo>; // boolean
type P = Parameters<typeof foo>; // [a: string, b: number] Keng tarqalgan xato. ReturnType<foo> deb yozish (typeofsiz). foo — bu qiymat, tip emas. Utility tipga funksiya tipi kerak, shuning uchun ReturnType<typeof foo> yozish shart.
Follow-up. "Bir conditional'da bir nechta infer bo'la oladimi?" — Ha: T extends Promise<infer U> ? U : T yoki hatto T extends [infer A, infer B] ? ... : .... Bir necha pozitsiyani parallel ushlash mumkin.
5. Narrowing va tip xavfsizligi
S: Type narrowing nima? typeof, instanceof, in qanday ishlatiladi? (Middle)
Ta'rif. Narrowing — keng tipni (union yoki unknown) kod oqimi (control flow) davomida aniqroq tipga qisqartirish. TS bu tekshiruvlarni "tushunadi" va shu blok ichida tipni toraytiradi.
Mexanizm. TS control flow analysis yuritadi: if (typeof x === "string") blogi ichida xni string deb biladi. Uch asosiy vosita:
typeof— primitivlar uchun ("string","number", ...).instanceof— class instansiyalari uchun.in— obyektda maydon borligini tekshirish uchun.
Kod misol.
function ishla(x: string | number) {
if (typeof x === "string") {
return x.toUpperCase(); // bu yerda x: string
}
return x.toFixed(2); // bu yerda x: number
}
class Mushuk { miyov() {} }
class It { vov() {} }
function ovoz(h: Mushuk | It) {
if (h instanceof Mushuk) h.miyov();
else h.vov();
}
type A = { yur: () => void };
type B = { suz: () => void };
function harakat(x: A | B) {
if ("yur" in x) x.yur(); // maydon borligiga qarab narrow
else x.suz();
} Keng tarqalgan xato. typeof null === "object" — bu JS'ning tarixiy xatosi. typeof x === "object" blogi ichida x hali null bo'lishi mumkin, shuning uchun avval x !== null tekshirish kerak.
Follow-up. "Nega if (x) bilan narrow qilinganda 0 yoki "" muammo beradi?" — Truthiness tekshiruvi 0, "", NaNni ham "false" deb chiqaradi. Aniq qiymat kerak bo'lsa x != null yoki aniq taqqoslash ishlating.
S: Custom type guard (is) nima? Discriminated union bilan qanday birga ishlatiladi? (Senior)
Ta'rif. Type guard — param is Tip return tipiga ega funksiya. U TS'ga "bu funksiya true qaytarsa, argument shu tipda" deb aytadi. Discriminated union — har variantda umumiy literal "teg" maydoni (discriminant) bo'lgan union.
Mexanizm. Type guard — narrowing'ni funksiyaga o'raladi. Discriminated union'da esa switch/if orqali teg maydoniga qarab TS avtomatik to'g'ri variantga narrow qiladi — bu eng ishonchli narrowing usuli.
Kod misol.
// Custom type guard
interface Baliq { suz: () => void }
interface Qush { uch: () => void }
function baliqmi(h: Baliq | Qush): h is Baliq {
return (h as Baliq).suz !== undefined;
}
function harakat(h: Baliq | Qush) {
if (baliqmi(h)) h.suz(); // narrow: Baliq
else h.uch();
}
// Discriminated union — eng toza pattern
type Holat =
| { turi: "yuklanmoqda" }
| { turi: "tayyor"; malumot: string[] }
| { turi: "xato"; xabar: string };
function render(h: Holat) {
switch (h.turi) { // "turi" — discriminant
case "yuklanmoqda": return "...";
case "tayyor": return h.malumot.join(","); // malumot mavjud
case "xato": return h.xabar; // xabar mavjud
}
} Keng tarqalgan xato. Type guard'ni yolg'on (xato mantiqli) yozish. h is Baliq deb va'da berib, ichida noto'g'ri tekshirsangiz, TS sizga ishonadi va runtime'da xato yuz beradi. Type guard — "dasturchi so'zi", TS uni tekshirmaydi.
Follow-up. "Discriminated union'da barcha holat qamrab olinganini qanday kafolatlaysiz?" — default blokda const _: never = h yozib exhaustiveness check qilish. Agar yangi variant qo'shsangiz va uni unutgan bo'lsangiz, TS shu joyda xato beradi.
S: unknown, any va never — uchtasi farqini tushuntiring. (Middle)
Ta'rif. any — tip tekshiruvini o'chiradi (har narsa mumkin). unknown — "har narsa, lekin ishlatishdan oldin tekshir/narrow qil" (xavfsiz any). never — "hech qachon yuz bermaydigan" tip (bo'sh to'plam).
Mexanizm. any tip tizimidan chiqib ketadi — hech qanday kafolat yo'q. unknown esa top type: unga hamma narsa tayinlanadi, lekin undan hech narsa (narrow qilmasdan) o'qib bo'lmaydi. never — bottom type: unga hech narsa tayinlanmaydi, lekin u har joyga tayinlanadi (union'da yo'qoladi).
Kod misol.
let a: any = 5;
a.toUpperCase(); // compile o'tadi, runtime'da qulaydi
let u: unknown = 5;
u.toUpperCase(); // Compile xatosi: avval narrow qil
if (typeof u === "string") u.toUpperCase(); //
function xatoTashla(msg: string): never { // hech narsa qaytarmaydi
throw new Error(msg);
}
type T = string | never; // never yo'qoladi string Keng tarqalgan xato. API javobini any deb qo'yib, xatolikni runtime'ga surish. To'g'ri yondashuv — unknown deb olish va validatsiya (masalan zod) orqali narrow qilish. any — "tip tekshiruvini butun zanjir bo'ylab o'chiradi", bu xavfli tarqaladi.
Follow-up. "never qayerda amaliy foyda beradi?" — Exhaustiveness check'da (const _: never = x), bo'sh massiv/xato funksiyalarida, va conditional type'larda "imkonsiz" tarmoqni belgilashda.
6. Ilg'or tip mexanizmlari
S: Mapped type nima? U qanday ishlaydi? (Senior)
Ta'rif. Mapped type — mavjud tipning barcha kalitlari bo'ylab aylanib, yangi tip yaratadi. Partial, Readonly, Record — barchasi shunga asoslangan.
Mexanizm. { [K in KalitlarUnion]: Qiymat } sintaksisi — har bir kalit uchun tipni qayta hisoblaydi. Modifikatorlar: ? (ixtiyoriy), readonly, va ularni olib tashlash uchun -?, -readonly. as bilan kalitlarni qayta nomlash (key remapping) ham mumkin.
Kod misol.
type MyPartial<T> = { [K in keyof T]?: T[K] }; // hammani ixtiyoriy qil
type Mutable<T> = { -readonly [K in keyof T]: T[K] }; // readonly'ni olib tashla
interface User { readonly id: number; ism: string; }
type M = Mutable<User>; // { id: number; ism: string } — endi o'zgaruvchan
// Key remapping — kalit nomini o'zgartirish
type Getterlar<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]
};
type UG = Getterlar<{ ism: string }>; // { getIsm: () => string } Keng tarqalgan xato. Mapped type ichida union kalitlarni noto'g'ri distributiv deb o'ylash. keyof T — kalitlar union'i, lekin mapped type ular bo'ylab aylanadi (har biri uchun alohida), distributiv conditional emas.
Follow-up. "Key remapping'da bir kalitni butunlay chiqarib tashlash mumkinmi?" — Ha, as never bilan: [K in keyof T as K extends "parol" ? never : K] — parol maydonini yo'q qiladi.
S: Conditional type va infer nima? Amaliy misolda tushuntiring. (Senior)
Ta'rif. Conditional type — T extends U ? X : Y ko'rinishidagi tip "if-else"i. infer — shart ichida noma'lum tipni ushlab olish.
Mexanizm. Agar T Uga mos kelsa X, aks holda Y tipi qaytadi. Union tip berilganda conditional distributiv ishlaydi — har bir a'zoga alohida qo'llaniladi (naked type parameter bo'lganda). infer esa pattern matching kabi — tipni "yechib" ichidagi qismni oladi.
Kod misol.
// Promise ichidagi tipni yechish
type Unwrap<T> = T extends Promise<infer U> ? U : T;
type A = Unwrap<Promise<string>>; // string
type B = Unwrap<number>; // number (Promise emas o'zi)
// Distributiv xatti-harakat
type FaqatString<T> = T extends string ? T : never;
type C = FaqatString<"a" | 1 | "b">; // "a" | "b" (union bo'ylab tarqaladi)
// Distributivni o'chirish uchun [] bilan o'rash:
type IsNever<T> = [T] extends [never] ? true : false; Keng tarqalgan xato. Distributiv xatti-harakatni unutish. T extends any ? T[] : never union'da kutilmagan natija beradi, chunki har a'zoga alohida qo'llanadi. Agar butun union'ni yaxlit tekshirmoqchi bo'lsangiz, [T] extends [U] bilan o'rang.
Follow-up. "infer qaysi pozitsiyalarda ishlaydi?" — Return tipi, parametr, generic argument, array element, tuple element, hatto template literal ichida ham. Ular pattern matching pozitsiyalari.
S: keyof va typeof operatorlari nima qiladi? Ular birga qanday ishlatiladi? (Middle)
Ta'rif. keyof T — tipning barcha kalitlarini union sifatida beradi. typeof x (tip kontekstida) — qiymatdan uning tipini chiqaradi.
Mexanizm. typeof — qiymat dunyosidan tip dunyosiga "ko'prik". keyof — obyekt tipining kalitlar union'ini. Ular birga tez-tez ishlatiladi: keyof typeof obj — mavjud obyektdan kalitlar union'ini olish.
Kod misol.
const konfig = {
port: 3000,
host: "localhost",
};
type Konfig = typeof konfig; // { port: number; host: string }
type Kalit = keyof typeof konfig; // "port" | "host"
function olish(kalit: keyof typeof konfig) {
return konfig[kalit]; // faqat mavjud kalit
}
olish("port"); //
olish("xato"); // Compile xatosi Keng tarqalgan xato. keyof any string | number | symbol beradi (kutilmagan). Va keyof obyektdagi runtime kalitlarni bermaydi — faqat tip darajasidagi kalitlarni. Runtime kalitlar uchun Object.keys() kerak (u esa string[] qaytaradi, aniq union emas).
Follow-up. "Object.keys(obj) nega keyof T[] emas, string[] qaytaradi?" — Chunki obyektda (structural typing sabab) e'lon qilinganidan ko'proq maydon bo'lishi mumkin — TS soundness uchun string[] beradi. Aniq union kerak bo'lsa, as (keyof T)[] bilan assertion qilinadi.
S: Index signature nima? Qachon ishlatiladi va qanday tuzoqlari bor? (Middle)
Ta'rif. Index signature — { [kalit: string]: Qiymat } — oldindan noma'lum kalitlarga ega obyekt tipini e'lon qilish.
Mexanizm. Index signature "bu obyektda har qanday string kalit bo'lishi mumkin, qiymati esa shu tipda" degani. Bu dinamik xaritalar (dictionary/map) uchun kerak. Kalit tipi string, number yoki symbol bo'la oladi.
Kod misol.
interface Lugat {
[soz: string]: string;
}
const l: Lugat = { salom: "hello", xayr: "bye" };
l.yangi = "new"; // har qanday string kalit mumkin
// Tuzoq: index signature bilan aniq maydon aralashuvi
interface Aralash {
[kalit: string]: number;
ism: string; // Xato: "ism" number bo'lishi kerak (index signature'ga bo'ysunadi)
} Keng tarqalgan xato. Index signature'li obyektdan o'qishda undefined ehtimolini unutish. l["mavjudEmas"] tipda string, lekin runtime'da undefined — noUncheckedIndexedAccess sozlamasi buni string | undefinedga aylantiradi (xavfsizroq).
Follow-up. "Index signature o'rniga Record<string, T> ishlatsam bo'ladimi?" — Ha, Record<string, string> aynan shu narsani beradi va ko'pincha o'qilishlicha (readable). Farqi kam — Record — mapped type ustiga qurilgan qulay alias.
7. Assertion va o'ziga xos konstruksiyalar
S: Type assertion (as) nima? U type casting'dan qanday farq qiladi? Xavfi nimada? (Middle)
Ta'rif. Type assertion — "TS'ga bu qiymat aynan shu tipda deb ishon" deyish (x as Tip). Bu casting emas — u runtime'da hech narsani o'zgartirmaydi, faqat compilerni ishontiradi.
Mexanizm. as faqat compile paytidagi belgi — hech qanday tekshiruv yoki konvertatsiya yo'q. Boshqa tillardagi casting qiymatni haqiqatan o'zgartiradi; TS assertion esa faqat "tip haqidagi fikringni o'zgartir" degani.
Kod misol.
const el = document.getElementById("x") as HTMLInputElement;
el.value = "salom"; // TS ishonadi (lekin runtime'da null bo'lsa qulaydi)
const x: unknown = "matn";
const uzunlik = (x as string).length; // narrow o'rniga assertion
// Xavfli: yolg'on assertion
const son = "salom" as unknown as number; // compile o'tadi, mantiqan yolg'on Keng tarqalgan xato. asni narrowing o'rniga ishlatib, runtime xatolarni yashirish. getElementById null qaytarishi mumkin — as buni yashiradi. To'g'ri yo'l — tekshirish (if (el) ...). Assertion — "oxirgi chora", tekshiruv o'rniga emas.
Follow-up. "as const ham type assertion'mi?" — Ha, lekin maxsus turi: u tipni kengaytirmaslik (narrow, readonly) uchun. Oddiy as Tip esa tipni majburan o'zgartiradi. as const xavfsiz, as Tip xavfli bo'lishi mumkin.
S: satisfies operatori nima? U asdan va oddiy tip annotatsiyasidan qanday farq qiladi? (Senior)
Ta'rif. satisfies (TS 4.9+) — qiymat berilgan tipga mos kelishini tekshiradi, lekin qiymatning aniq (narrow) tipini saqlab qoladi. Ya'ni "tekshir, lekin tipni kengaytirma".
Mexanizm. Oddiy annotatsiya (const x: T = ...) qiymat tipini Tga kengaytiradi (aniqlikni yo'qotadi). as esa tekshirmaydi, faqat majbur qiladi. satisfies — ikkalasining eng yaxshisi: tekshiradi va aniq tipni saqlaydi.
Kod misol.
type Ranglar = Record<string, [number, number, number]>;
// Annotatsiya bilan — aniqlik yo'qoladi
const a: Ranglar = { qizil: [255, 0, 0] };
a.qizil[0]; // , lekin a.qizil — [number, number, number], kalitlar cheklanmagan
// satisfies bilan — tekshiradi VA aniq tipni saqlaydi
const b = {
qizil: [255, 0, 0],
yashil: [0, 255, 0],
} satisfies Ranglar;
b.qizil; // aniq kalit, avtoto'ldirish ishlaydi
b.ochkok; // Compile xatosi: bunday kalit yo'q
b.qizil[0].toFixed(); // number ekanligi saqlangan Keng tarqalgan xato. satisfiesni as o'rnini bosuvchi deb o'ylash. as tipni majburan o'zgartiradi (xavfli bo'lishi mumkin), satisfies esa faqat tekshiradi va rad qila oladi — u hech qachon tipni yolg'on qilmaydi.
Follow-up. "Qachon satisfies, qachon annotatsiya?" — Aniq kalitlar/literal tiplarni saqlash kerak bo'lsa (config obyekti, ranglar palitrasi) — satisfies. Agar qiymatni ataylab kengroq tipga "yashirmoqchi" bo'lsangiz — annotatsiya.
S: Function overloading TS'da qanday ishlaydi? Union parametrdan qanday farqi bor? (Middle)
Ta'rif. Overloading — bitta funksiyaga bir necha imzo (signature) e'lon qilish. Har xil argument kombinatsiyasiga har xil return tipi berish imkonini beradi.
Mexanizm. TS'da bir nechta overload imzosi e'lon qilinadi, keyin bitta implementatsiya imzosi (funksiya tanasi bilan) yoziladi. Chaqiruvchi faqat overload imzolarni ko'radi; implementatsiya imzosi tashqaridan yashirin. Union parametr esa bitta imzo — return tipini kirishga bog'lay olmaydi.
Kod misol.
// Overload: kirish tipiga qarab return tipi o'zgaradi
function ol(x: string): string;
function ol(x: number): number;
function ol(x: string | number): string | number { // implementatsiya
return x;
}
const s = ol("a"); // tip: string (aniq)
const n = ol(5); // tip: number (aniq)
// Union bilan — return tipi kirishga bog'lanmaydi
function ol2(x: string | number): string | number { return x; }
const r = ol2("a"); // tip: string | number (aniqlik yo'q)Keng tarqalgan xato. Implementatsiya imzosini "birinchi overload" deb o'ylash. Implementatsiya imzosi tashqaridan ko'rinmaydi — u faqat tanani yozish uchun. Chaqiruvchilar faqat e'lon qilingan overload imzolarni ishlata oladi.
Follow-up. "Overload o'rniga generic yoki conditional type ishlatib bo'ladimi?" — Ko'p hollarda ha, va zamonaviy TS'da tavsiya etiladi: function ol<T extends string | number>(x: T): T. Overload murakkab holatlar (masalan turli argument soni) uchun qoladi.
8. Konfiguratsiya va ekotizim
S: tsconfig.jsonda strict nima yoqadi? Eng muhim sozlamalar qaysilar? (Middle)
Ta'rif. strict: true — bir nechta qat'iy tekshiruv bayroqlarini birdaniga yoqadigan "umbrella" sozlama. U TS'ning haqiqiy kuchini ochadi.
Mexanizm. strict quyidagilarni yoqadi: strictNullChecks (null/undefined'ni alohida tip qiladi), noImplicitAny (yashirin anyni taqiqlaydi), strictFunctionTypes (parametr contravariance), strictBindCallApply, strictPropertyInitialization, noImplicitThis, alwaysStrict, va boshqalar.
Kod misol.
{
"compilerOptions": {
"strict": true, // eng muhim — hammasini yoqadi
"noUncheckedIndexedAccess": true, // index natijasiga | undefined qo'shadi
"noImplicitReturns": true, // barcha yo'l qiymat qaytarishi shart
"noUnusedLocals": true,
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"esModuleInterop": true
}
}// strictNullChecks bilan:
function f(x?: string) {
return x.length; // x undefined bo'lishi mumkin
} Keng tarqalgan xato. strict: false bilan yangi loyiha boshlash. Bunda strictNullChecks o'chiq bo'ladi va null/undefined har joyga tarqaladi — TS'ning eng katta foydasi (null xavfsizligi) yo'qoladi. Doim strict: true bilan boshlang.
Follow-up. "noUncheckedIndexedAccess nega default emas?" — Chunki u juda ko'p mavjud kodni buzadi (arr[0] endi T | undefined). Ammo yangi loyihalarda tavsiya etiladi — massiv/obyekt kirishidagi eng ko'p uchraydigan xatolarni ushlaydi.
S: Declaration file (.d.ts) nima va nima uchun kerak? (Middle)
Ta'rif. .d.ts — faqat tip e'lonlarini saqlaydigan fayl (implementatsiyasiz). U JS kutubxonasiga TS tiplarini "qo'shib" beradi.
Mexanizm. .d.ts faylida faqat declare e'lonlar bo'ladi — kod (tana) yo'q. TS bu fayllardan tip ma'lumotini oladi, lekin ular JS chiqishga qo'shilmaydi. Kutubxona TS'da yozilgan bo'lsa, tsc avtomatik .d.ts generatsiya qiladi (declaration: true).
Kod misol.
// global.d.ts — global tip e'loni
declare global {
interface Window {
mening_api: { version: string };
}
}
// modul uchun tip (masalan tipsiz JS kutubxonaga)
declare module "eski-kutubxona" {
export function ishla(x: number): string;
}
// muhit o'zgaruvchilari tipi
declare namespace NodeJS {
interface ProcessEnv {
DATABASE_URL: string;
}
}
export {}; Keng tarqalgan xato. .d.ts faylga implementatsiya (funksiya tanasi) yozish — u yerda faqat e'lon bo'lishi kerak. Yana — export {}ni unutish: modul e'lonlarida fayl "modul" bo'lishi uchun kamida bitta import/export kerak, aks holda global scope'ga tushadi.
Follow-up. "@types/paket nima?" — DefinitelyTyped loyihasidan keladigan, tipsiz JS kutubxonalarga tip beruvchi alohida paketlar. Masalan npm i -D @types/lodash — lodashga TS tiplarini qo'shadi.
S: Decorator nima va TS'da qanday ishlaydi? (Middle)
Ta'rif. Decorator — class, metod, property yoki parametr ustiga qo'yiladigan, ularni o'zgartirish/qo'shimcha xatti-harakat berish uchun funksiya (@DecoratorNomi). Angular, NestJS, TypeORM kabi frameworklarda keng ishlatiladi.
Mexanizm. Decorator — e'lon paytida chaqiriladigan funksiya. TS'da ikki avlod bor: eski (experimentalDecorators bayrog'i, TC39 stage 2) va yangi standart (TS 5.0+, stage 3). Ular metadata biriktirish, DI (dependency injection), validatsiya uchun ishlatiladi.
Kod misol.
// Metod decorator (yangi standart, TS 5.0+)
function log<T extends (...args: any[]) => any>(
target: T,
context: ClassMethodDecoratorContext
) {
return function (this: any, ...args: any[]) {
console.log(`${String(context.name)} chaqirildi`);
return target.apply(this, args);
};
}
class Xizmat {
@log
salom(ism: string) {
return `Salom ${ism}`;
}
}// Eski decorator uchun tsconfig:
{ "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true } } Keng tarqalgan xato. Eski (experimentalDecorators) va yangi (stage 3) decorator sintaksisini aralashtirib yuborish. Ularning imzolari (signature) butunlay boshqacha. NestJS/Angular hozircha eski, standart TS 5+ esa yangisini ishlatadi — loyihaga qarab to'g'risini tanlang.
Follow-up. "emitDecoratorMetadata nima qiladi?" — reflect-metadata bilan birga tip ma'lumotini runtime'ga chiqaradi, DI konteynerlar (NestJS) tiplarni runtime'da o'qishi uchun. Bu — TS'ning "tiplar runtime'da yo'q" qoidasidan istisno.
S: Modullar TS'da qanday hal qilinadi? moduleResolution sozlamasi nega muhim? (Senior)
Ta'rif. Module resolution — TS'ning import yo'llarini haqiqiy fayllarga qanday bog'lashi. moduleResolution sozlamasi bu jarayonning algoritmini belgilaydi.
Mexanizm. Turli qiymatlar: node (klassik CommonJS), node16/nodenext (Node ESM qoidalari, package.json exports maydonini hisobga oladi), bundler (Vite/esbuild kabi bundler'lar mantiqi, kengaytmasiz importlarga ruxsat). Har biri fayl kengaytmasi, exports maydoni va index fayllarni boshqacha qidiradi.
Kod misol.
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "bundler", // zamonaviy bundler loyihalari uchun
"baseUrl": ".",
"paths": { // yo'l aliaslari
"@/*": ["src/*"]
}
}
}import { foo } from "@/utils/foo"; // "src/utils/foo"ga bog'lanadi Keng tarqalgan xato. paths alias qo'shib, uni faqat TS tushunishini unutish. Yakuniy runtime (Node, bundler) pathsni bilmaydi — bundler config (vite.config, tsconfig-paths) yoki tsc-aliasda alohida sozlash kerak. Aks holda compile o'tadi, runtime'da "modul topilmadi" xatosi chiqadi.
Follow-up. "type importi nima uchun kerak?" — import type { User } from "./types" — bu import faqat tip uchun ekanligini bildiradi va yakuniy JS'dan butunlay olib tashlanadi. isolatedModules/verbatimModuleSyntax bilan bu muhim — noto'g'ri import runtime'da keraksiz modul yuklashiga sabab bo'ladi.
9. Amaliy va tuzoq savollar
S: strictNullChecks yoqilgan va o'chirilgan holatda TS xatti-harakati qanday farq qiladi? (Senior)
Ta'rif. strictNullChecks — null va undefinedni alohida tiplar sifatida ko'radigan sozlama. O'chirilganda ular har qanday tipga "sokin" tayinlanadi.
Mexanizm. O'chirilganda (false): null/undefined deyarli har qanday tipning a'zosi — let x: string = null xatosiz o'tadi. Yoqilganda (true): null/undefinedni aniq union'ga qo'shish kerak (string | null), va foydalanishdan oldin narrow qilish shart.
Kod misol.
// strictNullChecks: false
let a: string = null; // (xavfli — sokin o'tadi)
a.toUpperCase(); // runtime'da qulaydi
// strictNullChecks: true
let b: string = null; // Compile xatosi
let c: string | null = null; // aniq belgilash
c.toUpperCase(); // avval null tekshir
if (c !== null) c.toUpperCase(); //
// Optional chaining va nullish coalescing bilan:
const uzunlik = c?.length ?? 0; Keng tarqalgan xato. Mavjud katta loyihada strictNullChecksni birdan yoqib, yuzlab xato olish. Yechim — bosqichma-bosqich (fayl-fayl yoki // @ts-expect-error bilan) migratsiya. Yangi loyihada esa boshdan yoqilishi shart.
Follow-up. "! (non-null assertion) nima?" — x!.length — "TS'ga bu yerda x null/undefined emas deb ishon". Bu ham as kabi xavfli — runtime tekshiruvi o'rniga emas, faqat compilerni tinchlantirish uchun.
S: Bu kod nega xato beradi? const arr: string[] = []; arr.push(1); va Object.keys tuzog'i. (Senior — tuzoq)
Ta'rif. TS'da ba'zi "ochiq ko'rinadigan" holatlar tip tizimining chuqur qoidalari (variance, structural typing, inference) tufayli kutilmagan natija beradi.
Mexanizm. string[]ga number push qilish — oddiy tip xatosi. Ammo tuzoqlar nozikroq: bo'sh massiv [] tipi kontekstsiz never[] yoki any[] bo'lishi mumkin; Object.keys structural typing sabab string[] qaytaradi; funksiya union return'i esa inference'ni chalg'itadi.
Kod misol.
const arr: string[] = [];
arr.push(1); // number string[]ga mos emas — kutilgan xato
// Tuzoq 1: kontekstsiz bo'sh massiv
const bosh = []; // tip: any[] (strict'da ham!)
bosh.push(1);
bosh.push("a"); // o'tadi — any[] xavfli
// Tuzoq 2: Object.keys aniqlik bermaydi
const user = { ism: "Ali", yosh: 30 };
Object.keys(user).forEach((k) => {
// k: string (─ "ism" | "yosh" EMAS!)
// user[k]; implicit any / index xatosi
});
// Tuzoq 3: readonly massivni o'zgartirish
const r = [1, 2] as const;
r.push(3); // readonly — push yo'q Keng tarqalgan xato. Object.keys(obj) natijasini keyof T[] deb o'ylash. TS ataylab string[] beradi (structural typing — obyektda ko'proq maydon bo'lishi mumkin). To'g'ri union kerak bo'lsa: (Object.keys(obj) as (keyof typeof obj)[]) — lekin bu assertion, xavfini bilib turing.
Follow-up. "Nega const bosh = [] never[] emas, any[]?" — Bu "evolving array" — TS uni push'lar bo'yicha kuzatib, kontekstda tipni "o'stiradi". Aniq tip berilsa (const bosh: number[] = []) bu xatti-harakat to'xtaydi va xavfsiz bo'ladi.
S: interfaceni extends qilib override qilganda nima bo'ladi? Va implements bilan extends farqi? (Senior)
Ta'rif. extends — meros/kengaytirish (interface yoki class). implements — class'ning berilgan interface shakliga rioya qilishini kafolatlaydi (lekin merosxo'rlik emas).
Mexanizm. Interface extends bilan bir necha interface'ni birlashtiradi va maydonlarni toraytirishi (mos bo'lsa) mumkin. Class implements bilan interface'ni "va'da" qiladi, lekin uning implementatsiyasini yozish class'ning o'ziga qoladi. implements faqat tekshiradi, hech narsa meros qilmaydi.
Kod misol.
interface A { x: number; y: number; }
interface B extends A {
x: 5; // toraytirish mumkin (5 — number'ning ostki tipi)
// x: string; // mos emas — kengaytirib bo'lmaydi
}
interface Yura { yur(): void; }
class Odam implements Yura {
yur() { console.log("yuryapman"); } // o'zi yozishi shart
// implements meros bermaydi — faqat tekshiradi
}
class Bola extends Odam { // extends — meros oladi (yur() tayyor)
} Keng tarqalgan xato. implements merosxo'rlik beradi deb o'ylash. implements hech narsa bermaydi — u faqat class kerakli maydon/metodlarga ega ekanligini tekshiradi. Kodni class o'zi yozishi shart. Kod meros olish uchun extends kerak.
Follow-up. "Bir class bir necha interface'ni implements qila oladimi?" — Ha: class C implements A, B, D. Lekin extends bilan faqat bitta class'dan meros oladi (JS'da ko'p merosxo'rlik yo'q). Interface'lar esa cheksiz.
S: void va undefined return tiplari farqi nimada? Callback'da qanday tuzoq bor? (Middle — tuzoq)
Ta'rif. undefined — aynan undefined qiymati. void — "return qiymati ahamiyatsiz/e'tiborsiz" degan kontekstual tip. Ular o'xshasa-da, callback tiplashda muhim farq beradi.
Mexanizm. void return tipiga ega funksiya aslida qiymat qaytarishi mumkin — TS uni shunchaki e'tiborsiz qoldiradi. Bu ataylab qilingan: void callback joyiga qiymat qaytaruvchi funksiyani berish mumkin (masalan arr.forEachga arr.push — push number qaytaradi, forEach void kutadi).
Kod misol.
type Callback = () => void;
const cb: Callback = () => 42; // o'tadi! void qiymatni e'tiborsiz qoldiradi
// Amaliy tuzoq:
const raqamlar: number[] = [];
const manba = [1, 2, 3];
manba.forEach((n) => raqamlar.push(n));
// push number qaytaradi, forEach callback void kutadi — ishlaydi
// Lekin aniq undefined talab qilinsa:
type Aniq = () => undefined;
const c2: Aniq = () => 42; // number undefined emas Keng tarqalgan xato. voidni "hech narsa qaytarmaydi" deb qat'iy tushunish. Aslida — "qaytgan qiymat ishlatilmaydi". Bu farq Promise<void> va async funksiyalarda ham muhim: void qiymat borligini taqiqlamaydi, faqat e'tiborsiz qoldiradi.
Follow-up. "() => void tipidagi callback qaytargan qiymatni ishlatsam bo'ladimi?" — Yo'q. void return tipi bo'lgani uchun natija void tipida bo'ladi va uni ishlatib bo'lmaydi — TS uni "yo'q" deb ko'radi, garchi runtime'da qiymat mavjud bo'lsa ham.
S: Template literal types nima? Amaliy misolda tushuntiring. (Senior)
Ta'rif. Template literal type — string literal tiplarni shablon yordamida birlashtirib yangi string tiplar yaratish (`${A}-${B}`). Bu tip darajasidagi string manipulyatsiyasi.
Mexanizm. Xuddi JS template string kabi, lekin tip darajasida. Union bilan birga kombinatsiyalar hosil qiladi. Uppercase, Lowercase, Capitalize, Uncapitalize — ichki (intrinsic) string manipulyatsiya tiplari bilan birga ishlaydi.
Kod misol.
type Yonalish = "yuqori" | "past";
type Oʻq = "x" | "y";
type Klass = `${Yonalish}-${Oʻq}`;
// "yuqori-x" | "yuqori-y" | "past-x" | "past-y" (4 kombinatsiya)
// Amaliy: event nomlaridan handler nomlari
type Hodisa = "click" | "hover";
type Handler = `on${Capitalize<Hodisa>}`;
// "onClick" | "onHover"
// CSS o'lchov birligi
type Olcham = `${number}px` | `${number}%`;
const w: Olcham = "10px"; //
const h: Olcham = "10"; // birlik yo'q Keng tarqalgan xato. Katta union'lar bilan template literal ishlatib kombinatsiya portlashi (combinatorial explosion) hosil qilish. ${A}${B}${C} uch katta union bilan minglab tip yaratadi va compiler sekinlashadi yoki "type instantiation is excessively deep" xatosini beradi.
Follow-up. "Template literal ichida infer ishlatib bo'ladimi?" — Ha: type Ajrat<S> = S extends \${infer A}-${infer B}` ? [A, B] : never`. Bu string'ni tip darajasida bo'laklarga ajratadi — yo'l parametrlari (route params) tiplashda ishlatiladi.
S: never tipi bilan exhaustiveness check qanday qilinadi? Nega bu foydali? (Middle)
Ta'rif. Exhaustiveness check — union'ning barcha variantlari qamrab olinganini compile paytida kafolatlash. never tipi bu yerda "qolgan variant yo'q" belgisidir.
Mexanizm. Discriminated union'ni switch bilan ishlaganda, default blokda qolgan qiymatni neverga tayinlaymiz. Agar barcha case qamrab olingan bo'lsa, qolgan tip never — muammosiz. Agar yangi variant qo'shsangiz-u case yozmasangiz, qolgan tip never bo'lmaydi va TS xato beradi.
Kod misol.
type Shakl =
| { turi: "doira"; r: number }
| { turi: "kvadrat"; tomon: number };
function yuza(s: Shakl): number {
switch (s.turi) {
case "doira": return Math.PI * s.r ** 2;
case "kvadrat": return s.tomon ** 2;
default:
const _tekshir: never = s; // hamma variant qamralgan s: never
return _tekshir;
}
}
// Agar { turi: "uchburchak" } qo'shsangiz-u case yozmasangiz:
// default'da s: { turi: "uchburchak" } — never emas COMPILE XATOSI Keng tarqalgan xato. default: return 0 yozib, exhaustiveness check'ni yo'qotish. Bunda yangi variant qo'shilsa TS ogohlantirmaydi — jimgina noto'g'ri natija qaytadi. never tekshiruvi aynan shu xatoni oldini oladi.
Follow-up. "Bu runtime'da qanday xatti-harakat qiladi?" — neverga tayinlash faqat compile-time tekshiruvi; runtime'da hech qanday qo'shimcha kod yo'q. Agar qat'iy runtime himoya kerak bo'lsa, defaultda throw new Error(...) ham qo'shiladi.
S: Generic funksiyada type inference qachon muvaffaqiyatsiz bo'ladi? Uni qanday tuzatasiz? (Senior)
Ta'rif. TS ko'pincha generic tiplarni argumentlardan avtomatik chiqaradi (inference), lekin ba'zi holatlarda u chalg'iydi yoki juda keng/tor tip beradi.
Mexanizm. Inference argumentlardan "orqaga" ishlaydi. Muammolar: (1) argument yo'q joyda (faqat return'dan chiqarish kerak bo'lsa), (2) union widening, (3) juda umumiy pozitsiya. Yechimlar: aniq generic argument berish (f<string>(...)), constraint qo'shish, yoki default type berish.
Kod misol.
function yarat<T>(): T[] { // T'ni chiqarib bo'lmaydi — argument yo'q
return [];
}
const a = yarat(); // T = unknown unknown[]
const b = yarat<number>(); // aniq berish kerak
// Widening muammosi:
function birinchi<T>(x: T): T { return x; }
const c = birinchi("salom"); // T = string (widened, "salom" emas)
const d = birinchi<"salom">("salom"); // literal saqlanadi
// Constraint bilan yo'naltirish:
function kalitlar<T extends object>(o: T): (keyof T)[] {
return Object.keys(o) as (keyof T)[];
} Keng tarqalgan xato. Inference muvaffaqiyatsizligini any bilan "yopish". const a: any[] = yarat() — xatoni yashiradi. To'g'ri yechim — generic argumentni aniq berish yoki funksiya imzosini qayta loyihalash (argumentdan chiqariladigan qilib).
Follow-up. "NoInfer<T> nima?" — TS 5.4+ utility: ma'lum pozitsiyada inference'ni to'xtatadi. Masalan function f<T>(a: T, b: NoInfer<T>[]) — T faqat adan chiqariladi, b unga ta'sir qilmaydi. Default qiymatlarni to'g'ri chiqarishda foydali.
Eng ko'p so'raladigan savollar
Quyidagilar intervyularda eng tez-tez uchraydi — ularni ravon, misol bilan gapira olishga tayyor turing:
interfacevatypefarqi va qachon qaysini tanlaysiz? — Obyekt shakli va merging/extends kerak bo'lsainterface; union/intersection/mapped uchuntype.any,unknown,neverfarqi. —anytekshiruvni o'chiradi;unknownxavfsiz, narrow shart;never— hech qachon yuz bermaydi.- Generic nima va nega kerak? — Kirish va chiqish tipini bog'lab, kodni qayta ishlatiladigan va tip-xavfsiz qilish.
- Type narrowing qanday ishlaydi? —
typeof/instanceof/in/type guard orqali keng tipni control flow davomida toraytirish. - Utility tiplar (
Partial,Pick,Omit,Record) nima qiladi? — Mavjud tipdan mapped type asosida yangi tip yasaydi. strictsozlamasi nima yoqadi? — AsosanstrictNullChecksvanoImplicitAny; TS'ning haqiqiy kuchini ochadi.- Structural typing nima? — Tiplar nomga emas, shaklga qarab mos keladi (duck typing).
- TS tiplari runtime'da mavjudmi? — Yo'q (type erasure). Runtime validatsiya uchun
zodkabi vositalar kerak. as(assertion) xavfli, nega? — Runtime'da hech narsa tekshirmaydi; narrowing o'rniga ishlatilsa xatolarni yashiradi.satisfiesasdan nimasi bilan yaxshi? — Tekshiradi va aniq tipni saqlaydi; hech qachon tipni yolg'on qilmaydi.- Discriminated union va exhaustiveness check. — Umumiy teg maydoni +
nevertekshiruvi bilan barcha holatni kafolatlash. keyofvatypeofbirga qanday ishlaydi? —keyof typeof obj— mavjud obyektdan type-safe kalitlar union'i.
Maslahat. Senior darajaga:
infer, conditional/mapped types, variance va inference tuzoqlarini misol bilan tushuntira olish sizni ajratib turadi. Yodlash emas — "nega shunday?" savoliga javob bering.
Eslatma: Barcha kod misollari strict: true sozlamasida yozilgan deb faraz qilinadi. Intervyu davomida inglizcha atamalar (narrowing, discriminated union, structural typing) shu holicha ishlatilishi normal — ular xalqaro standart.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!