Type predicate (is) va exhaustiveness checking (never)
Tekshiruv funksiyasi yozdingiz — isFoydalanuvchi(x). Lekin if (isFoydalanuvchi(x)) dan keyin TypeScript x ni hali unknown deb biladi. Funksiyadan narrowing qilish uchun type predicate kerak.
Type predicate — x is T
Qaytish turi parametr is Tur ko'rinishida yoziladi:
type Foydalanuvchi = { ism: string; email: string };
function isFoydalanuvchi(x: unknown): x is Foydalanuvchi {
return (
typeof x === "object" && x !== null &&
"ism" in x && typeof (x as any).ism === "string" &&
"email" in x && typeof (x as any).email === "string"
);
}
function qayta(x: unknown): string {
if (isFoydalanuvchi(x)) {
return x.email; // ✅ x: Foydalanuvchi
}
return "Noma'lum";
}
Array.filter bilan
const aralash: (string | null | undefined)[] =
["Ali", null, "Vali", undefined, "Soli"];
// ❌ — filter ishlaydi, lekin tur hali union
const a = aralash.filter(x => x !== null && x !== undefined);
// tur: (string | null | undefined)[]
// ✅ — type predicate bilan
const b = aralash.filter((x): x is string => typeof x === "string");
// tur: string[] ✅
Exhaustiveness checking — never bilan
Discriminated union da barcha holatlar ko'rilganini kafolatlash:
type Holat =
| { tur: "a"; x: number }
| { tur: "b"; y: string }
| { tur: "c"; z: boolean };
function qayta(h: Holat): string {
switch (h.tur) {
case "a": return String(h.x);
case "b": return h.y;
case "c": return String(h.z);
default:
const _exhaustive: never = h; // ← yangi holat qo'shilsa — xato shu yerda
throw new Error(`Ko'rilmagan: ${JSON.stringify(h)}`);
}
}
Holat ga { tur: "d" } qo'shilsa va switch da ko'rilmasa:
Type '{ tur: "d" }' is not assignable to type 'never'
assertNever helper
function assertNever(x: never): never {
throw new Error(`Ko'rilmagan holat: ${JSON.stringify(x)}`);
}
// Har joyda ishlatish
switch (h.tur) {
case "a": return ...;
case "b": return ...;
default: return assertNever(h);
}
Type predicate xavfi
TypeScript "ishoning" deydi — ichki tekshiruv noto'g'ri bo'lsa runtime xato:
// ❌ — noto'g'ri predicate
function isSon(x: unknown): x is number {
return typeof x === "string"; // bug!
}
if (isSon("matn")) {
// TypeScript number deb biladi — lekin aslida string
}
Predicate ichidagi tekshiruv albatta to'g'ri bo'lishi shart.
Xulosa
// Type predicate
function isXXX(x: unknown): x is XXX {
return /* tekshiruv */;
}
// Array.filter
arr.filter((x): x is string => typeof x === "string")
// Exhaustiveness — never
switch (h.tur) {
case "a": ...;
case "b": ...;
default: const _: never = h; // yangi tur qo'shilsa — kompilyator xato
}
Keyingi dars
32-dars: Generics nima uchun kerak? — muammo va yechim