11.14-bob: TypeScript bilan React
11-QISM — Frontend: React · 14-mavzu
1. Kirish va motivatsiya
7-QISM'da TypeScript'ni o'rgandik — turlar, interface, generics, utility types. Endi uni React bilan birlashtiramiz, va bu birikma — zamonaviy professional React loyihasining standarti. 2026-yilda deyarli barcha jiddiy React loyiha TypeScript'da yoziladi (oddiy JavaScript emas), va buning sabablari aniq: xato compile paytida tutiladi (foydalanuvchi ko'rishidan oldin), autocomplete (muharrir har props/funksiyani taklif qiladi), va refactoring xavfsiz bo'ladi (nomni o'zgartirsangiz, ishlatilgan hamma joy avtomatik topiladi). Proplarni noto'g'ri uzatish, mavjud bo'lmagan maydonga murojaat, funksiyaga noto'g'ri argument — bularning hammasini TypeScript kod yozayotgan paytingizda tutadi.
Lekin React + TypeScript o'z nozikliklariga ega: props turlarini qanday yozish (interface yoki type?), childrenning turi nima, useState/useRef/useReducer turlarini qanday belgilash, hodisa (event) turlari, generic komponentlar, va eng ko'p munozara qiladigan React.FC — ishlatish kerakmi yoki yo'qmi. Bu bobda aynan shu amaliy nozikliklarni o'rganamiz. 11.10-bobda Zod + TypeScript birikmasini (forma) ko'rganmiz — endi uni butun React kontekstiga kengaytiramiz: type-safe komponent, hook, API qatlami.
Bu bob: nega TS React'da (xato compile'da, autocomplete, refactoring), setup (.tsx, react-ts, @types), komponent va props turlari (interface/type, optional, default), children turi (ReactNode), hooklar turlari (useState<T>, useRef, useReducer), event turlari (onChange/onClick/onSubmit), generic komponentlar (List<T>), custom hook turlari, React.FC munozarasi (nega ko'pincha ishlatilmaydi), utility types React'da (Omit/Pick/Partial — props), Context turlari, va Zod + TS birikmasi (type-safe API). Har mavzu to'liq, amaliy va zamonaviy holatda, izohli kod bilan ochib beriladi.
O'xshatish: TypeScript React'da — bu qurilishdagi texnik chizma va o'lcham nazorati. JavaScript bilan React yozish — bu chizmasiz bino qurish: ishlayveradi, lekin bir devorni noto'g'ri o'lchab qo'ysangiz (props'ni noto'g'ri uzatsangiz), buni faqat bino qulaganda (foydalanuvchi xato ko'rganda) bilasiz. TypeScript — bu aniq chizma + o'lcham tekshirgich: har bir g'isht (komponent) qanday ulanishini (qaysi props, qaysi turda) oldindan belgilaysiz, va agar noto'g'ri ulasangiz — chizma darrov qizil chiroq beradi (muharrirda xato — kod yozayotgan paytingizda, bino qurilmasdan oldin). Bundan tashqari, chizma sizga avtomat yordamchi beradi (autocomplete — "bu yerga shu g'isht mos keladi"), va bino tuzilishini o'zgartirganda (refactoring) — chizma barcha bog'liq joyni avtomatik yangilaydi. Tajribali quruvchi hech qachon chizmasiz qurmaydi.
Nega muhim?
- Professional standart — 2026'da jiddiy React loyiha = TypeScript (JS emas); ish e'lonlarida talab.
- Kam xato — props/maydon/argument xatolari compile paytida (foydalanuvchi emas) tutiladi.
- Unumdorlik — autocomplete, refactoring, "go to definition" — kod yozish tezroq va ishonchli.
- Komanda — turlar — "jonli hujjat" (boshqa dasturchi komponentni qanday ishlatishni darrov ko'radi).
2. Nazariya — chuqur tushuntirish
2.1. Nega TypeScript React'da
JAVASCRIPT (xato ish vaqtida — foydalanuvchi ko'radi):
<UserCard name={user.nam} /> // "nam" — xato (name kerak) undefined bug
function UserCard({ name, age }) { return <h2>{nme}</h2>; } // "nme" — xato crash
// bu xatolar FAQAT ilova ishlaganda (yoki umuman) seziladi
TYPESCRIPT (xato KOD yozayotganda — muharrirda qizil):
interface Props { name: string; age: number; }
<UserCard name={user.nam} /> // muharrir DARROV: "nam mavjud emas"
function UserCard({ name, age }: Props) { return <h2>{nme}</h2>; } // "nme topilmadi"
3 ASOSIY FOYDA:
Xato compile paytida (foydalanuvchi ko'rishidan OLDIN)
Autocomplete (har props/metod/maydon taklif qilinadi — tez yozish)
Refactoring xavfsiz (nom o'zgarsa — barcha ishlatish joyi topiladi)
TS — React'da xatolarni ERTA (yozaytganda) tutadi (JS — kech, ish vaqtida)
Turlar — "jonli hujjat" (komponentni qanday ishlatish — kodda ko'rinadi)Nega TypeScript React'da — uchta asosiy foyda. JavaScript'da xatolar ish vaqtida (runtime) seziladi — masalan
<UserCard name={user.nam} />(xato —namekerak edi) yoki funksiyada{nme}(xato) — bular faqat ilova ishlaganda (yoki umuman sezilmasdan, jim bug bo'lib) namoyon bo'ladi. TypeScript'da esa bu xatolar kod yozayotgan paytda muharrirda qizil chiziq bilan ko'rsatiladi (compile paytida — foydalanuvchi ko'rishidan oldin). Uch asosiy foyda: (1) xato erta tutiladi (compile paytida, runtime emas); (2) autocomplete — muharrir har bir props, metod, maydonni taklif qiladi (tez va ishonchli yozish); (3) refactoring xavfsiz — nom yoki tuzilishni o'zgartirganda, barcha ishlatish joylari avtomatik topiladi (qo'lda qidirmasdan). Ikki muhim nuqta: (1) TS xatolarni erta (yozayotganda) tutadi — bu junior va senior loyihasining sifat farqini belgilaydi; (2) turlar — "jonli hujjat" (living documentation): komponentni qanday ishlatish (qaysi props, qaysi turda) kodning o'zida ko'rinadi (alohida hujjat yozish kerak emas). Aynan shu sabab TypeScript zamonaviy React standartiga aylandi.
2.2. Setup — .tsx, react-ts, @types
YANGI LOYIHA (TS bilan — 11.3):
npm create vite@latest my-app -- --template react-ts # React + TypeScript
FAYL KENGAYTMASI:
.tsx — JSX'li TypeScript fayl (komponentlar) // React komponent .tsx
.ts — JSX'siz TypeScript (util, hook, types) // oddiy mantiq .ts
TURLAR (@types — kutubxonalar uchun):
- react, react-dom turlari — react-ts shablonda avtomatic
- boshqa kutubxona: npm i -D @types/<paket> (agar o'zi TS bermasa)
tsconfig.json (asosiy sozlamalar — 7.1):
"jsx": "react-jsx", // yangi JSX transform (import React kerak emas — 11.2)
"strict": true, // qattiq tekshiruv (tavsiya — barcha himoya)
┌────────────────────────────────────────────────────────────┐
│ Komponent .tsx | Mantiq/util/types .ts │
│ react-ts shablon — turlar va sozlama tayyor │
└────────────────────────────────────────────────────────────┘
react-ts shablon 11.3-bob — turlar, tsconfig, sozlama tayyor (qo'lda sozlash kerak emas)
strict: true — barcha himoyani yoq (null tekshiruv, implicit any yo'q — 7.1)Setup — React + TypeScript loyihasini sozlash. Yangi loyiha:
npm create vite@latest my-app -- --template react-ts11.3-bob — React + TypeScript shabloni (turlar,tsconfig, sozlamalar tayyor). Fayl kengaytmalari:.tsx(JSX'li TypeScript — React komponentlari uchun),.ts(JSX'siz — util funksiyalari, custom hooklar, type ta'riflari uchun). Turlar (@types):react/react-domturlarireact-tsshablonda avtomatik o'rnatilgan; boshqa kutubxona o'z turlarini bermasa (npm i -D @types/<paket>bilan o'rnatasiz — masalan@types/node).tsconfig.jsonasosiy sozlamalari 7.1-bob:"jsx": "react-jsx"(yangi JSX transform —import Reactkerak emas — 11.2: 2.4),"strict": true(qattiq tekshiruv — tavsiya, barcha himoyani yoqadi: null tekshiruv, implicitanyyo'q). Ikki nuqta: (1)react-tsshabloni 11.3-bob — turlar,tsconfig, sozlama tayyor (qo'lda sozlash kerak emas, darrov ishlaysiz); (2)strict: true— barcha TypeScript himoyasini yoqadi (eng muhim sozlama — usiz TypeScriptning foydasi yarmiga kamayadi). Setup oddiy —react-tsshabloni bilan bir buyruqda tayyor.
2.3. Komponent va props turlari — interface/type
PROPS TURI — interface yoki type bilan (komponentga kiruvchi ma'lumot):
// interface bilan (keng ishlatiladi):
interface ButtonProps {
text: string;
variant: "primary" | "danger"; // union — faqat shu qiymatlar 7.4-bob
disabled?: boolean; // ? — ixtiyoriy
onClick: () => void; // funksiya turi
}
function Button({ text, variant, disabled, onClick }: ButtonProps) {
return <button className={variant} disabled={disabled} onClick={onClick}>{text}</button>;
}
// type bilan (ekvivalent — ko'pincha union/utility uchun):
type ButtonProps = { text: string; variant: "primary" | "danger" };
INTERFACE vs TYPE (React props uchun):
- interface — kengaytiriladigan (extends), object shakli uchun (an'anaviy)
- type — union, intersection, utility types uchun (moslashuvchanroq — 7.2)
ikkalasi ham ishlaydi; izchillik muhim (jamoa tanlovi)
Props turi — komponentning "shartnomasi" (qanday ishlatish — autocomplete + tekshiruv)
? — ixtiyoriy prop; union ("a"|"b") — faqat ruxsat etilgan qiymatlar (7.4)Komponent va props turlari — React + TypeScript'ning eng asosiy ko'nikmasi. Props turi
interfaceyokitypebilan belgilanadi:interface ButtonProps { text: string; variant: "primary" | "danger"; disabled?: boolean; onClick: () => void }— har props nomi va turi yoziladi. Muhim elementlar: union ("primary" | "danger"— faqat shu qiymatlar ruxsat etiladi — 7.4),?(ixtiyoriy prop —disabled?), funksiya turi (onClick: () => void). Komponentga turni qo'shasiz:function Button({ text, variant }: ButtonProps).interfacevstype(React props uchun):interface— kengaytiriladigan (extends), obyekt shakli uchun an'anaviy;type— union, intersection, utility types uchun moslashuvchanroq 7.2-bob; ikkalasi ham ishlaydi, eng muhimi — izchillik (jamoa bir uslubni tanlab, unga rioya qilsin). Ikki nuqta: (1) props turi — komponentning "shartnomasi" (contract): u qanday ishlatilishini aniq belgilaydi (noto'g'ri props — darrov xato, va autocomplete props'ni taklif qiladi); (2)?ixtiyoriy props uchun, union ruxsat etilgan qiymatlarni cheklash uchun (variant="warning"— agar union'da yo'q bo'lsa — xato). Bu — type-safe komponentning poydevori.
2.4. children turi — ReactNode
CHILDREN — komponent ichidagi JSX (11.2: 2.8) — turi ReactNode:
interface CardProps {
title: string;
children: React.ReactNode; // ReactNode — JSX, matn, raqam, array, null... (hammasi)
}
function Card({ title, children }: CardProps) {
return <div className="card"><h3>{title}</h3>{children}</div>;
}
CHILDREN TURLARI (qaysi birini qachon):
- React.ReactNode — eng keng (JSX, string, number, array, null — odatda SHU)
- React.ReactElement — faqat JSX element (string/null emas — kamroq)
- (children?: ReactNode) — ixtiyoriy children
PropsWithChildren (yordamchi — children'ni avtomatik qo'shadi):
function Card({ title, children }: React.PropsWithChildren<{ title: string }>) {...}
children turi — deyarli har doim React.ReactNode (eng moslashuvchan)
PropsWithChildren<Props> — children'ni qo'lda yozmasdan qo'shadi (qulay)
childrenturi — komponent ichidagi JSX'ning (11.2: 2.8) turi. Eng keng va standart tur —React.ReactNode: u JSX element, matn (string), raqam (number), array,null,undefined, boolean — ya'ni komponent ichiga qo'yish mumkin bo'lgan hamma narsani qamraydi.interface CardProps { title: string; children: React.ReactNode }. Children turlari (qaysi birini qachon):React.ReactNode(eng keng — odatda shuni ishlatasiz);React.ReactElement(faqat JSX element — string/null qabul qilmaydi — kamroq, qattiqroq); ixtiyoriy children —children?: ReactNode.PropsWithChildren(yordamchi tur) —childrenni avtomatik qo'shadi:React.PropsWithChildren<{ title: string }>—title+children(qo'ldachildren: ReactNodeyozish o'rniga). Ikki nuqta: (1)childrenturi deyarli har doimReact.ReactNode(eng moslashuvchan — barcha bola turlarini qabul qiladi); (2)PropsWithChildren<Props>—childrenni qo'lda yozmasdan qo'shadigan qulay yordamchi (o'rovchi komponentlar — Card, Layout, Modal — uchun ideal). Bu — wrapper komponentlarning standart turi.
2.5. useState turlari — inference, generic, union
useState — TURNI ko'pincha O'ZI ANGLAYDI (inference), ba'zan qo'lda:
// 1. INFERENCE (TS boshlang'ich qiymatdan turni ANGLAYDI — qo'lda kerak emas):
const [count, setCount] = useState(0); // number (0 dan)
const [name, setName] = useState(""); // string
const [open, setOpen] = useState(false); // boolean
// 2. GENERIC (murakkab tur — qo'lda belgila):
const [user, setUser] = useState<User | null>(null); // User obyekt yoki null
const [items, setItems] = useState<Product[]>([]); // Product massivi
// useState<T>(boshlang'ich) — T turni aniq beradi
// 3. UNION (bir nechta holat):
const [status, setStatus] = useState<"idle" | "loading" | "error">("idle");
QACHON GENERIC kerak:
- boshlang'ich null/bo'sh ([]) — TS turni anglay olmaydi (null/never[])
- union turi (status — bir nechta qiymat)
Oddiy qiymat (0, "", false) — inference yetadi (generic kerak emas)
null/bo'sh massiv/union — generic kerak: useState<User|null>(null), useState<T[]>([])
useStateturlari — ko'pincha TypeScript turni o'zi anglaydi (inference), ba'zan qo'lda belgilanadi. (1) Inference — boshlang'ich qiymatdan tur avtomatik aniqlanadi:useState(0)number,useState("")string,useState(false)boolean(qo'lda tur yozish kerak emas). (2) Generic — murakkab tur uchun qo'lda:useState<User | null>(null)(User obyekt yoki null),useState<Product[]>([])(Product massivi) —useState<T>(boshlang'ich)bilan turni aniq berasiz. (3) Union — bir nechta holat:useState<"idle" | "loading" | "error">("idle")(status). Qachon generic kerak: (a) boshlang'ich qiymatnullyoki bo'sh massiv ([]) bo'lganda — TS turni anglay olmaydi (nullyokinever[]deb biladi, keyinsetUser(realUser)xato beradi); (b) union turi (status). Ikki qoida: (1) oddiy qiymat (0,"",false) bilan boshlasangiz — inference yetadi (generic ortiqcha); (2)null, bo'sh massiv, yoki union bilan — generic kerak (useState<User|null>(null),useState<T[]>([])). Bu —useStateni to'g'ri turlashning amaliy qoidasi (eng ko'p ishlatiladigan hook).
2.6. useRef turlari — DOM va mutable
useRef — ikki xil ishlatish (11.5: 2.12, 2.13), ikki xil tur:
// 1. DOM REF (element turi + null — boshlang'ich):
const inputRef = useRef<HTMLInputElement>(null); // <input> elementi (yoki null)
inputRef.current?.focus(); // ?. — null bo'lishi mumkin (render'dan oldin)
// DOM tur: HTMLInputElement, HTMLDivElement, HTMLButtonElement... (element'ga mos)
// 2. MUTABLE QIYMAT (render'siz qiymat — 11.5: 2.13):
const countRef = useRef<number>(0); // number (boshlang'ich 0)
const timerRef = useRef<number | null>(null); // interval ID (number yoki null)
countRef.current += 1; // .current — to'g'ridan o'zgartiriladi
DOM TUR QANDAY TOPISH:
<input> HTMLInputElement | <div> HTMLDivElement | <button> HTMLButtonElement
<form> HTMLFormElement | <a> HTMLAnchorElement | <canvas> HTMLCanvasElement
DOM ref: useRef<HTMLXElement>(null) — null boshlang'ich (DOM render'dan keyin to'ladi)
inputRef.current?.focus() — ?. (null tekshiruv — strict mode — 2.5)
useRefturlari — ref'ning ikki ishlatilishiga (11.5: 2.12, 2.13) ikki tur. (1) DOM ref —useRef<HTMLInputElement>(null)— element turi (HTMLInputElement) va boshlang'ichnull(DOM render'dan keyin to'ladi). IshlatishdainputRef.current?.focus()—?.(optional chaining) kerak, chunkicurrentnullbo'lishi mumkin (render'dan oldin). DOM turlari elementga mos:<input>HTMLInputElement,<div>HTMLDivElement,<button>HTMLButtonElement,<form>HTMLFormElement,<canvas>HTMLCanvasElement, va h.k. (2) Mutable qiymat (render'siz — 11.5: 2.13) —useRef<number>(0)(number),useRef<number | null>(null)(interval ID);.currentni to'g'ridan o'zgartirasiz (countRef.current += 1). Ikki nuqta: (1) DOM ref —useRef<HTMLXElement>(null)(nullboshlang'ich, element turi), vacurrentni?.bilan ishlat (strict mode null tekshiruvi talab qiladi — 2.5); (2) DOM turni topish oson — element nomini katta harf bilanHTML+Element(HTMLInputElement). To'g'ri DOM tur — autocomplete'ni ham beradi (inputRef.current?.keyin barcha input metodlari taklif qilinadi).
2.7. useReducer turlari — state va action union
useReducer — state turi + action turi (discriminated union — 7.4):
interface State { count: number; loading: boolean; }
type Action = // discriminated union — har action o'z shakli
| { type: "increment" }
| { type: "decrement" }
| { type: "set"; payload: number } // payload faqat shu action'da
| { type: "loading"; payload: boolean };
function reducer(state: State, action: Action): State { // turlar — type-safe
switch (action.type) {
case "increment": return { ...state, count: state.count + 1 };
case "set": return { ...state, count: action.payload }; // payload — number (TS biladi)
case "loading": return { ...state, loading: action.payload }; // payload — boolean
default: return state;
}
}
const [state, dispatch] = useReducer(reducer, { count: 0, loading: false });
dispatch({ type: "set", payload: 5 }); // type-safe (payload number kerak)
dispatch({ type: "set" }); // xato (set payload talab qiladi)
Action — discriminated union (type maydon ajratadi; payload har action'da har xil — 7.4)
TS payload turini "type"dan aniqlaydi (set number, loading boolean) — type-safe dispatch
useReducerturlari — state va action turlarini belgilaydi (11.6 davomi). State turi oddiy interface (interface State { count: number; loading: boolean }). Action turi — discriminated union 7.4-bob: har action o'z shakliga ega,typemaydon ularni ajratadi —type Action = { type: "increment" } | { type: "set"; payload: number } | { type: "loading"; payload: boolean }. Bu — TypeScript'ning eng kuchli imkoniyatlaridan biri: reducer ichidaswitch (action.type)qilganda, harcaseda TS payload turini aniq biladi (case "set"action.payload— number;case "loading"boolean). Reducerga turlar qo'shasiz:function reducer(state: State, action: Action): State. Vadispatchham type-safe:dispatch({ type: "set", payload: 5 }), lekindispatch({ type: "set" })(payload talab qilinadi),dispatch({ type: "set", payload: "x" })(number kerak). Ikki nuqta: (1) action — discriminated union (typemaydon orqali ajratiladi, har action'ning o'z payload turi) — bu TS'ning reducer bilan eng go'zal birikmasi; (2) TS payload turinitypedan avtomatik aniqlaydi (type-safe dispatch va reducer). Bu — murakkab state mantig'ini butunlay xavfsiz qiladi (noto'g'ri action — compile xatosi).
2.8. Event turlari — onChange, onClick, onSubmit
HODISA (EVENT) TURLARI — handler funksiyaga to'g'ri event turi:
// INPUT onChange:
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
setValue(e.target.value); // e.target.value — string (TS biladi)
}
// BUTTON onClick:
function handleClick(e: React.MouseEvent<HTMLButtonElement>) {
e.preventDefault();
}
// FORM onSubmit:
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
}
// KEYBOARD:
function handleKey(e: React.KeyboardEvent<HTMLInputElement>) {
if (e.key === "Enter") {...}
}
INLINE — TS turni O'ZI anglaydi (qo'lda kerak emas):
<input onChange={(e) => setValue(e.target.value)} /> // e — avtomatik ChangeEvent (inference)
┌────────────────────────────────────────────────────────────┐
│ ChangeEvent (input) | MouseEvent (click) | FormEvent (form) │
│ KeyboardEvent (key) | FocusEvent (focus/blur) │
└────────────────────────────────────────────────────────────┘
Inline handler — TS event turni o'zi anglaydi (alohida funksiyada qo'lda yoz)
Event<HTMLXElement> — element turini ham beradi (e.target/currentTarget to'g'ri turda)Event turlari — hodisa handler'lariga to'g'ri tur. Asosiy event turlari:
React.ChangeEvent<HTMLInputElement>(input/select onChange —e.target.valuestring),React.MouseEvent<HTMLButtonElement>(onClick),React.FormEvent<HTMLFormElement>(onSubmit),React.KeyboardEvent<HTMLInputElement>(onKeyDown —e.key),React.FocusEvent(onFocus/onBlur). Har biri generic argument oladi — element turi (<HTMLInputElement>) — bue.target/e.currentTargetni to'g'ri turda beradi. Muhim qulaylik: inline handler'larda TS turni o'zi anglaydi (inference) —<input onChange={(e) => setValue(e.target.value)} />—eavtomatikChangeEventdeb biladi (qo'lda tur yozish kerak emas). Faqat alohida funksiyada (komponentdan tashqarida yoki yuqorida e'lon qilingan) tur qo'lda yoziladi (function handleChange(e: React.ChangeEvent<HTMLInputElement>)). Ikki nuqta: (1) inline handler — TS event turni avtomatik anglaydi (eng qulay); alohida funksiya — qo'lda tur ber; (2)Event<HTMLXElement>— element turini ham beradi (autocomplete:e.target.value,e.currentTarget.disabled— to'g'ri turda). Bu — forma va interaktiv komponentlarni type-safe qiladi (e.target.valueni noto'g'ri ishlatish — compile xatosi).
2.9. Generic komponentlar — List
GENERIC KOMPONENT — har qanday tur bilan ishlaydigan, lekin TYPE-SAFE komponent:
interface ListProps<T> { // T — generic tur 7.3-bob
items: T[];
renderItem: (item: T) => React.ReactNode; // har element uchun UI
keyExtractor: (item: T) => string | number; // key (11.4: 2.13)
}
function List<T>({ items, renderItem, keyExtractor }: ListProps<T>) {
return <ul>{items.map(item => <li key={keyExtractor(item)}>{renderItem(item)}</li>)}</ul>;
}
// Ishlatish — TS turni ANGLAYDI (User yoki Product):
<List
items={users} // User[]
renderItem={(user) => user.name} // user — User (TS biladi, autocomplete)
keyExtractor={(user) => user.id}
/>
// items User[] bo'lsa — renderItem'dagi user AVTOMATIK User turida (type-safe)
┌────────────────────────────────────────────────────────────┐
│ Generic komponent: <T> — har tur bilan, lekin type-safe │
│ (List<User>, List<Product> — bir komponent, turli tur) │
└────────────────────────────────────────────────────────────┘
Generic komponent — qayta ishlatiladigan + type-safe (List, Table, Select, Combobox)
items turidan renderItem item turini ANGLAYDI (autocomplete + tekshiruv)Generic komponentlar — har qanday tur bilan ishlaydigan, lekin type-safe komponentlar (7.3 — generics React'da). Misol —
List<T>:interface ListProps<T> { items: T[]; renderItem: (item: T) => React.ReactNode; keyExtractor: (item: T) => string | number }—Tgeneric tur (har qanday bo'lishi mumkin). Komponent ham generic:function List<T>({ items, renderItem, keyExtractor }: ListProps<T>). Ishlatishda TypeScript turni anglaydi:<List items={users} renderItem={(user) => user.name} ... />—itemsUser[]bo'lganda,renderItemdagiuseravtomatikUserturida (autocomplete —user.name,user.emailtaklif qilinadi, vauser.xyzxato). Bir xilListkomponentiUser[],Product[],Order[]— har tur bilan, lekin har birida type-safe. Ikki nuqta: (1) generic komponent — qayta ishlatiladigan + type-safe birikmasi (List, Table, Select, Combobox, DataGrid — universal komponentlar); (2) eng kuchli tomoni —itemsturidan TSrenderItem/keyExtractordagi element turini avtomatik anglaydi (turni ikki marta yozish kerak emas, va mos kelmaslik — compile xatosi). Bu — kutubxona darajasidagi universal komponentlarni type-safe qurishning usuli.
2.10. Custom hook turlari
CUSTOM HOOK 11.7-bob — qaytarish turini belgilash (yoki inference):
// 1. INFERENCE (TS qaytarish turini o'zi anglaydi — ko'pincha yetadi):
function useToggle(initial = false) {
const [on, setOn] = useState(initial);
const toggle = useCallback(() => setOn(o => !o), []);
return [on, toggle] as const; // as const — tuple turi ([boolean, () => void])
}
const [isOpen, toggle] = useToggle(); // isOpen: boolean, toggle: () => void (type-safe)
// 2. ANIQ QAYTARISH TURI (obyekt — murakkab hook):
interface UseFetchResult<T> {
data: T | null;
loading: boolean;
error: string | null;
}
function useFetch<T>(url: string): UseFetchResult<T> { // generic — har tur uchun
const [data, setData] = useState<T | null>(null);
// ...
return { data, loading, error };
}
const { data } = useFetch<User[]>("/api/users"); // data: User[] | null (type-safe)
as const — massiv qaytaranda tuple turi (useState kabi [value, setter] — aniq turlar)
Generic hook — useFetch<User[]> — qaytgan data turini chaqiruvchi belgilaydi (type-safe)Custom hook turlari — custom hook'larni 11.7-bob type-safe qilish. (1) Inference — TS qaytarish turini ko'pincha o'zi anglaydi:
function useToggle(initial = false) { ...; return [on, toggle] as const }— diqqat:as constmuhim — usiz TS[on, toggle]ni(boolean | (() => void))[](aralash massiv) deb biladi,as constbilan tuple ([boolean, () => void]) — aniq turlar (xuddiuseStatekabi[value, setter]). (2) Aniq qaytarish turi — murakkab hook (obyekt qaytaradigan) uchun interface:interface UseFetchResult<T> { data: T | null; loading: boolean; error: string | null }, va generic hook:function useFetch<T>(url: string): UseFetchResult<T>—useFetch<User[]>("/api/users")data: User[] | null(type-safe). Ikki nuqta: (1)as const— massiv qaytaradigan hook'da tuple turi uchun zarur (aks holda destructuring noto'g'ri turlanadi); (2) generic hook —useFetch<User[]>— chaqiruvchi qaytgan ma'lumot turini belgilaydi (data avtomatik to'g'ri turda — autocomplete va tekshiruv). Bu — custom hook'larni butun loyiha bo'ylab type-safe qiladi (qaytgan qiymat turi har doim aniq).
2.11. React.FC munozarasi — nega ko'pincha ishlatilmaydi
React.FC (FunctionComponent) — komponent turini belgilashning ESKI usuli:
// React.FC bilan (eski — endi KAM tavsiya):
const Button: React.FC<ButtonProps> = ({ text }) => <button>{text}</button>;
// To'g'ridan props turi bilan (ZAMONAVIY tavsiya):
function Button({ text }: ButtonProps) { return <button>{text}</button>; }
NEGA React.FC KAM ISHLATILADI (2026):
Ilgari children'ni AVTOMATIK qo'shardi (endi yo'q — React 18'da olib tashlandi)
Generic komponentlar bilan noqulay (React.FC<Props<T>> — chalkash)
Ortiqcha (props turini to'g'ridan yozish — soddaroq, aniqroq)
TAVSIYA: to'g'ridan props turi (function Button({...}: Props) yoki const arrow)
children kerak bo'lsa — Props ichida aniq yoz (children: ReactNode — 2.4)
React.FC — eski uslub (zarari yo'q, lekin ortiqcha); ZAMONAVIY — to'g'ridan props turi
Bu — munozara mavzu; jamoa izchilligi muhim (lekin ko'pchilik React.FC'dan voz kechdi)
React.FCmunozarasi — React + TypeScript'ning eng ko'p munozara qilingan mavzusi.React.FC(FunctionComponent) — komponent turini belgilashning eski usuli:const Button: React.FC<ButtonProps> = ({ text }) => .... Zamonaviy tavsiya — to'g'ridan props turi:function Button({ text }: ButtonProps) {...}(yoki arrow function bilanconst Button = ({ text }: ButtonProps) => ...). NegaReact.FCkam ishlatiladi (2026): (1) ilgarichildrenni avtomatik qo'shardi (qulay edi), lekin React 18'da bu olib tashlandi (endiReact.FCchildrenni avtomatik bermaydi — afzalligi yo'qoldi); (2) generic komponentlar bilan noqulay (React.FC<Props<T>>— chalkash); (3) ortiqcha — props turini to'g'ridan yozish soddaroq va aniqroq. Tavsiya: to'g'ridan props turi (function Button({...}: Props));childrenkerak bo'lsa — Props ichida aniq yozing (children: ReactNode— 2.4) yokiPropsWithChildren. Ikki nuqta: (1)React.FC— eski uslub (zarari yo'q, lekin ortiqcha); zamonaviy React jamiyati to'g'ridan props turini afzal ko'radi; (2) bu munozara mavzu — jamoa izchilligi muhim (bir uslubni tanlab, unga rioya qiling), lekin yangi loyihadaReact.FCsiz boshlash tavsiya etiladi. Bu — amaliy, ko'p uchraydigan dizayn qarori.
2.12. Utility types React'da — Omit, Pick, Partial
UTILITY TYPES 7.4-bob React props bilan juda foydali (mavjud turni qayta ishlatish):
// HTML element props'ini KENGAYTIRISH (button'ning barcha props'i + o'zimizniki):
interface ButtonProps extends React.ComponentProps<"button"> { // barcha <button> props
variant: "primary" | "danger"; // + o'z props'imiz
}
// onClick, disabled, type, className... HAMMASI avtomatik (qo'lda yozMASDAN)
// OMIT (ba'zi props'ni OLIB tashlash):
type InputProps = Omit<React.ComponentProps<"input">, "size"> & { size: "sm" | "lg" };
// input'ning barcha props'i, LEKIN "size"ni o'zimizniki bilan almashtirish
// PICK (faqat ba'zi props):
type Coords = Pick<DOMRect, "top" | "left">; // faqat top, left
// PARTIAL (barcha props ixtiyoriy — tahrirlash/yangilash):
function updateUser(id: string, data: Partial<User>) {...} // User'ning ba'zi maydonlari
React.ComponentProps<"button"> — element'ning BARCHA props'ini beradi (kengaytirish uchun)
Omit/Pick/Partial — mavjud turni moslab qayta ishlatish (7.4 — DRY)Utility types React'da — TypeScript utility types 7.4-bob React props bilan juda foydali (mavjud turni qayta ishlatish — DRY).
React.ComponentProps<"button">— HTML element'ning barcha props'ini beradi:interface ButtonProps extends React.ComponentProps<"button"> { variant: "primary" }— buButtonga<button>ning barcha standart props'ini (onClick,disabled,type,className,aria-*...) avtomatik qo'shadi (qo'lda yozish kerak emas) + o'z props'imiz (variant).Omit— ba'zi props'ni olib tashlash:Omit<React.ComponentProps<"input">, "size"> & { size: "sm" | "lg" }(input props'i, lekinsizeni o'zimizniki bilan almashtirish).Pick— faqat ba'zi props (Pick<DOMRect, "top" | "left">).Partial— barcha props ixtiyoriy (tahrirlash/yangilash —Partial<User>— User'ning ba'zi maydonlari). Ikki nuqta: (1)React.ComponentProps<"element">— custom komponentga HTML element props'ini "meros qilish" uchun ideal (custom Input/Button — native input'ning barcha imkoniyatini oladi —<Input onChange={...} disabled placeholder="..." />); (2) Omit/Pick/Partial — mavjud turni moslab qayta ishlatish (DRY — 7.4). Bu — kutubxona darajasidagi komponentlarni to'liq type-safe va native HTML bilan mos qiladi.
2.13. Context va Zod + TS birikmasi
CONTEXT TURI — createContext'ga tur berish (11.5: 2.11):
interface AuthContextType {
user: User | null;
login: (creds: Credentials) => Promise<void>;
logout: () => void;
}
const AuthContext = createContext<AuthContextType | null>(null); // null boshlang'ich
// Custom hook — null tekshiruv bilan (type-safe):
function useAuth() {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error("useAuth AuthProvider ichida"); // null xato (TS: ctx endi AuthContextType)
return ctx; // tur: AuthContextType (null emas)
}
ZOD + TS (11.10 davomi) — sxema tur (single source — 5.9):
const userSchema = z.object({ id: z.string(), name: z.string(), age: z.number() });
type User = z.infer<typeof userSchema>; // sxemadan tur (qo'lda interface yo'q)
// API javobini tekshirish + turlash (type-safe):
const user: User = userSchema.parse(await res.json()); // runtime tekshiruv + compile turi
createContext<T | null>(null) + hook'da null tekshiruv (type-safe Context)
z.infer — sxemadan tur (validatsiya + tur bir manba — 5.9, 11.10)Context va Zod + TS birikmasi — ikki muhim integratsiya. Context turi (11.5: 2.11):
createContext<AuthContextType | null>(null)— tur generic argument sifatida (boshlang'ichnull); custom hook'da null tekshiruv:function useAuth() { const ctx = useContext(AuthContext); if (!ctx) throw new Error(...); return ctx }—if (!ctx) throwdan keyin TypeScriptctxniAuthContextType(null emas) deb biladi (type narrowing — 7.5), shuning uchun ishlatishda null tekshiruv kerak emas. Zod + TS (11.10 davomi, 5.9):const userSchema = z.object({...})type User = z.infer<typeof userSchema>— sxemadan tur avtomatik (qo'lda interface yozish kerak emas, sxema = yagona manba); va API javobini tekshirish + turlash —const user: User = userSchema.parse(await res.json())(runtime validatsiya + compile-time tur — ham server javobi to'g'riligini tekshiradi, ham type-safe qiladi). Ikki nuqta: (1) Context —createContext<T | null>(null)+ hook'da null tekshiruv (type-safe va xato xabari bilan — 11.7: Misol 14); (2) Zod —z.inferbilan sxemadan tur (validatsiya va tur bir manba — full-stack izchillik, 5.9, 11.10), vaparsebilan runtime API javobini xavfsiz qilish. Bu — to'liq type-safe React ilovasining yakuniy bog'lanishi (komponent hook Context API — hammasi turlangan).
2.14. JSX.Element vs ReactNode, ComponentProps, Record
QAYTARISH TURI — komponent nima qaytaradi (JSX.Element vs ReactNode):
function A(): JSX.Element { return <div />; } // AYNAN bitta element
function B(): React.ReactNode { return <div />; } // keng (fragment, string, null ham)
// ODATDA qaytarish turini QO'LDA yozmang — TS o'zi anglaydi (inference eng yaxshi)
JSX.Element vs ReactNode (farq):
- JSX.Element — faqat bitta JSX element (React.createElement natijasi)
- ReactNode — element + string + number + array + null + boolean (KENGROQ)
children uchun ReactNode 2.4-bob; qaytarish uchun — inference (qo'lda yozish shart emas)
ComponentProps<typeof X> — MAVJUD komponent props turini olish (qayta e'lon qilmasdan):
function Button(props: { text: string; variant: "a" | "b" }) {...}
type ButtonProps = React.ComponentProps<typeof Button>; // { text; variant } — avtomatik
// o'rovchi/HOC komponent yozganda foydali (props'ni takrorlamaslik)
Record<K, V> — kalitqiymat xaritasi props uchun:
interface Props {
styles: Record<string, string>; // { [key]: string } — CSS obyekti
labels: Record<"uz" | "en", string>; // FAQAT shu kalitlar (majburiy)
}
Qaytarish turini yozmang — inference (JSX.Element/ReactNode qo'lda kamdan-kam)
ComponentProps<typeof X> — mavjud komponent props'ini olish (DRY — 2.12 davomi)
Record<K, V> — xarita props (kalit turi + qiymat turi bir joyda)JSX.Element vs ReactNode,
ComponentProps<typeof X>,Record— uchta amaliy nozik nuqta. (1) Qaytarish turi — komponent nima qaytaradi:JSX.Element(aynan bitta JSX element) yokiReact.ReactNode(kengroq — element, string, number, array,null,boolean). Farq:childrenuchunReactNodeishlatiladi (2.4 — hamma narsani qamraydi), lekin komponent qaytarish turini odatda qo'lda yozmaysiz — TS uni inference bilan o'zi aniqlaydi (bu eng ishonchli, chunki fragment yoki shartlinullqaytarsangiz ham to'g'ri turlaydi). Faqat kerak bo'lsa,ReactNodeni afzal ko'ring (JSX.Elementjuda tor — fragment yokinullbilan xato beradi). (2)ComponentProps<typeof X>— mavjud komponentning props turini qayta e'lon qilmasdan olish:type ButtonProps = React.ComponentProps<typeof Button>—Buttonprops interface'iexportqilinmagan bo'lsa ham, uni oladi (o'rovchi komponent, HOC, yoki wrapper yozganda props'ni takrorlamaslik uchun ideal — DRY, 2.12 davomi). (3)Record<K, V>— kalitqiymat xaritasi turi:Record<string, string>(ixtiyoriy string kalitlar — masalan inline CSS obyekti), yokiRecord<"uz" | "en", string>(aniq kalitlar — ikkalasi ham majburiy, biror til yo'q bo'lsa — xato). Uch nuqta: (1) komponent qaytarish turini yozmang — inference eng yaxshi; (2)ComponentProps<typeof X>— mavjud komponentdan props "meros" olish; (3)Record— lug'at/xarita shaklidagi props uchun (i18n label'lar, config obyektlari). Bu — kundalik amaliyotda tez-tez uchraydigan uchta nozik tur.
2.15. forwardRef turlari — ref uzatuvchi komponent
forwardRef (11.5: 2.14) — komponentga tashqaridan ref berish, TIP bilan:
interface InputProps {
label: string;
error?: string;
}
// forwardRef<REF_TURI, PROPS_TURI> — ikki generic argument:
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ label, error }, ref) => { // ref — ikkinchi argument
return (
<div>
<label>{label}</label>
<input ref={ref} aria-invalid={!!error} /> {/* ref shu <input>'ga */}
</div>
);
}
);
Input.displayName = "Input"; // devtools uchun (arrow — nom yo'q)
// Ishlatish — ref type-safe (HTMLInputElement):
const ref = useRef<HTMLInputElement>(null);
<Input ref={ref} label="Email" /> // ref.current — HTMLInputElement | null
forwardRef<ElementTuri, PropsTuri> — birinchi = ref turi, ikkinchi = props
displayName — arrow funksiyada nom yo'q (devtools "ForwardRef" o'rniga aniq nom)
React 19'da forwardRef kerak emas — ref oddiy prop bo'ldi (versiyaga qarab)
forwardRefturlari — ref'ni ota-komponentdan bola-komponent ichidagi DOM element'ga uzatuvchi komponent (11.5: 2.14), tip bilan.React.forwardRefikki generic argument oladi: birinchi — ref element turi (HTMLInputElement), ikkinchi — props turi (InputProps):React.forwardRef<HTMLInputElement, InputProps>((props, ref) => ...). Funksiya ichidarefikkinchi argument sifatida keladi va uni bola element'ga uzatasiz (<input ref={ref} />).displayNameqo'shish tavsiya etiladi (Input.displayName = "Input") — arrow funksiyada nom bo'lmagani uchun React DevTools'da "ForwardRef" o'rniga aniq nom ko'rsatiladi. Ishlatishda ref to'liq type-safe:const ref = useRef<HTMLInputElement>(null); <Input ref={ref} ... />—ref.currentavtomatikHTMLInputElement | nullturida. Uch nuqta: (1)forwardRef<ElementTuri, PropsTuri>— argumentlar tartibi teskari (avval ref turi, keyin props — chalkashmang); (2)displayNameqo'shing (devtools uchun); (3) muhim versiya farqi — React 19'dan boshlabforwardRefkerak emas,refoddiy props sifatida uzatiladi (function Input({ label, ref }: InputProps & { ref?: React.Ref<HTMLInputElement> })) — lekin ko'p loyiha hali React 18'da, shuning uchunforwardRefni bilish shart. Bu — dizayn-tizim (design system) komponentlarining (Input, Button) muhim qismi.
2.16. Polymorphic komponent — as prop, ElementType
POLYMORPHIC KOMPONENT — turli HTML teg'da render bo'ladigan komponent (as prop):
// Oddiy holat (ElementType — har qanday teg/komponent):
interface TextProps {
as?: React.ElementType; // qaysi teg: "h1", "p", "span", Link...
children: React.ReactNode;
}
function Text({ as: Component = "span", children }: TextProps) {
return <Component>{children}</Component>; // as render'da teg
}
<Text as="h1">Sarlavha</Text> // <h1> bo'lib render
<Text as="p">Matn</Text> // <p> bo'lib render
// TO'LIQ TYPE-SAFE polymorphic (as teg props'ini ham to'g'ri oladi — ilg'or):
type PolymorphicProps<E extends React.ElementType> = {
as?: E;
children: React.ReactNode;
} & Omit<React.ComponentPropsWithoutRef<E>, "as" | "children">; // teg'ning native props'i
function Box<E extends React.ElementType = "div">({ as, ...rest }: PolymorphicProps<E>) {
const Component = as || "div";
return <Component {...rest} />;
}
<Box as="a" href="/uz">Havola</Box> // href — <a>'da bor (type-safe); <button>'da xato
as?: React.ElementType — komponent qaysi teg'da render bo'lishini tanlash (Button, Text, Box)
ComponentPropsWithoutRef<E> — tanlangan teg'ning native props'i (as="a" href, as="button" type)
Ilg'or naqsh — dizayn-tizim komponentlarida (bir Box, ko'p teg — type-safe)Polymorphic komponent — bir komponent turli HTML teg (yoki boshqa komponent) sifatida render bo'ladi —
asprop orqali tanlanadi. Oddiy holat:interface TextProps { as?: React.ElementType; children: React.ReactNode }—React.ElementTypehar qanday teg ("h1","p","span") yoki komponentni qabul qiladi; ichidaconst Component = as; return <Component>{children}</Component>—<Text as="h1"><h1>bo'lib render,<Text as="p"><p>. Bu bittaText/Box/Buttonkomponentini turli semantik teg'da ishlatishga imkon beradi (dizayn-tizimning asosiy naqshi). To'liq type-safe (ilg'or) versiya generic bilan quriladi:function Box<E extends React.ElementType = "div">({ as, ...rest }: PolymorphicProps<E>)— bundaReact.ComponentPropsWithoutRef<E>tanlangan teg'ning native props'ini ham to'g'ri turlaydi:<Box as="a" href="/uz">—href<a>'da bor (ruxsat), lekin<Box as="button" href="...">—href<button>'da yo'q (compile xatosi). Uch nuqta: (1)as?: React.ElementType— komponentga "qaysi teg'da render bo'lasiz" deb aytish (semantik moslashuvchanlik); (2)ComponentPropsWithoutRef<E>— tanlangan teg'ning props'ini avtomatik oladi (as="a"href,as="input"value); (3) bu ilg'or naqsh — dizayn-tizim kutubxonalarida (Chakra UI, Radix, MUI) keng ishlatiladi.ComponentPropsWithoutRefComponentPropsdan farqi — urefni chiqarib tashlaydi (polymorphic'darefalohida boshqariladi). Bu — kutubxona darajasidagi eng murakkab, lekin eng kuchli tiplash naqshi.
2.17. Type-safe loyiha tafakkuri
TYPE-SAFE REACT LOYIHA (xulosa — qatlamma-qatlam turlash):
┌──────────────────────────────────────────────────────────┐
│ Komponent props (interface — 2.3) │
│ │
│ Hooklar (useState<T>, custom hook — 2.5, 2.10) │
│ │
│ Context (createContext<T> — 2.13) │
│ │
│ API qatlami (Zod schema + z.infer — 2.13, 5.9) │
│ │
│ Backend (bir xil Zod schema — 5.9 — full-stack type-safe) │
└──────────────────────────────────────────────────────────┘
AMALIY MASLAHATLAR:
strict: true (barcha himoya — 2.2)
any'dan qoch (unknown + tekshiruv yoki aniq tur — 7.5)
Inference'ga ishon (oddiy holatda qo'lda tur yozma — 2.5)
Zod API chegarasida (server javobi — runtime + tur — 2.13)
React.FC emas, to'g'ridan props turi (2.11)
Type-safe — komponentdan API'gacha (va backend'gacha — Zod) ZANJIR (full-stack)
TS — "to'sqinlik" emas, YORDAMCHI (xato erta, autocomplete, ishonchli refactoring)Type-safe loyiha tafakkuri — bobning yakuniy xulosasi. Type-safe React loyiha qatlamma-qatlam turlanadi: komponent props (interface — 2.3) hooklar (
useState<T>, custom hook — 2.5, 2.10) Context (createContext<T>— 2.13) API qatlami (Zod schema +z.infer— 2.13) backend (bir xil Zod schema — 5.9 — full-stack type-safe). Ya'ni ma'lumot serverdan komponentga qadar har qatlamda turlangan (mos kelmaslik — compile xatosi). Amaliy maslahatlar:strict: true(barcha himoya — 2.2);anydan qoch (unknown+ tekshiruv yoki aniq tur — 7.5 —anyTypeScript himoyasini o'chiradi); inference'ga ishon (oddiy holatda qo'lda tur yozma — 2.5); Zod'ni API chegarasida ishlat (server javobi — runtime + tur — 2.13);React.FCemas, to'g'ridan props turi 2.11-bob. Ikki yakuniy tamoyil: (1) type-safe — komponentdan API'gacha (va backend'gacha — Zod) zanjir (full-stack — ma'lumot oqimi butunlay xavfsiz); (2) TypeScript — "to'sqinlik" emas, yordamchi: u xatolarni erta tutadi, autocomplete beradi, refactoring'ni xavfsiz qiladi — boshida biroz ko'proq yozasiz, lekin ko'p marta ko'proq vaqt va xatoni tejaysiz. Bu — professional React loyihasining poydevori.
3. Sintaksis — tez ma'lumotnoma
PROPS 2.3-bob: interface Props { name: string; variant: "a"|"b"; opt?: boolean }
function C({ name }: Props) {...}
CHILDREN 2.4-bob: children: React.ReactNode | React.PropsWithChildren<Props>
useState 2.5-bob: useState(0) | useState<User|null>(null) | useState<T[]>([])
useRef 2.6-bob: useRef<HTMLInputElement>(null) | useRef<number>(0)
useReducer 2.7-bob: type Action = {type:"x"} | {type:"set"; payload:number} // discriminated union
EVENT 2.8-bob: e: React.ChangeEvent<HTMLInputElement> | React.FormEvent<HTMLFormElement>
GENERIC 2.9-bob: function List<T>({ items }: ListProps<T>) {...}
HOOK 2.10-bob: return [a, b] as const | function useFetch<T>(): Result<T>
HTML PROPS 2.12-bob: extends React.ComponentProps<"button"> | Omit<...,"size">
CONTEXT 2.13-bob: createContext<T | null>(null) + if (!ctx) throw
ZOD 2.13-bob: type User = z.infer<typeof userSchema> | schema.parse(data)
COMPPROPS 2.14-bob: React.ComponentProps<typeof Button> | Record<"a"|"b", string>
forwardRef 2.15-bob: React.forwardRef<HTMLInputElement, Props>((props, ref) => ...)
POLYMORPH 2.16-bob: as?: React.ElementType | ComponentPropsWithoutRef<E> (as prop)4. Batafsil kod namunalari
Misol 1 — Komponent props (interface — 2.3)
interface ButtonProps {
text: string;
variant: "primary" | "danger" | "ghost"; // union — faqat shu qiymatlar
disabled?: boolean; // ixtiyoriy
onClick: () => void;
}
function Button({ text, variant, disabled = false, onClick }: ButtonProps) {
return (
<button className={`btn btn-${variant}`} disabled={disabled} onClick={onClick}>
{text}
</button>
);
}
// Ishlatish — type-safe:
<Button text="Saqlash" variant="primary" onClick={() => {}} /> //
// <Button text="X" variant="warning" /> // "warning" union'da yo'q + onClick yetishmaydiMisol 2 — children turi (2.4)
interface CardProps {
title: string;
children: React.ReactNode; // JSX, matn, array... (hammasi)
footer?: React.ReactNode; // ixtiyoriy children-kabi prop
}
function Card({ title, children, footer }: CardProps) {
return (
<div className="card">
<h3>{title}</h3>
<div className="body">{children}</div>
{footer && <div className="footer">{footer}</div>}
</div>
);
}
// Yoki PropsWithChildren bilan:
// function Card({ title, children }: React.PropsWithChildren<{ title: string }>) {...}Misol 3 — useState turlari (2.5)
interface User { id: string; name: string; }
function Component() {
const [count, setCount] = useState(0); // number (inference)
const [name, setName] = useState(""); // string
const [user, setUser] = useState<User | null>(null); // generic (null boshlang'ich)
const [items, setItems] = useState<User[]>([]); // generic (bo'sh massiv)
const [status, setStatus] = useState<"idle" | "loading" | "done">("idle"); // union
setUser({ id: "1", name: "Ali" }); // type-safe
// setUser({ id: "1" }); // name yetishmaydi
return null;
}Misol 4 — useRef turlari (2.6)
function SearchForm() {
const inputRef = useRef<HTMLInputElement>(null); // DOM ref
const timerRef = useRef<number | null>(null); // mutable (interval ID)
useEffect(() => {
inputRef.current?.focus(); // ?. — null bo'lishi mumkin (2.6)
}, []);
const startTimer = () => {
timerRef.current = window.setInterval(() => console.log("tick"), 1000);
};
const stopTimer = () => {
if (timerRef.current) clearInterval(timerRef.current);
};
return <input ref={inputRef} />;
}Misol 5 — useReducer turlari (discriminated union — 2.7)
interface State { count: number; loading: boolean; }
type Action =
| { type: "increment" }
| { type: "decrement" }
| { type: "set"; payload: number }
| { type: "setLoading"; payload: boolean };
function reducer(state: State, action: Action): State {
switch (action.type) {
case "increment": return { ...state, count: state.count + 1 };
case "decrement": return { ...state, count: state.count - 1 };
case "set": return { ...state, count: action.payload }; // payload: number (TS biladi)
case "setLoading": return { ...state, loading: action.payload }; // payload: boolean
default: return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0, loading: false });
return (
<div>
<p>{state.count}</p>
<button onClick={() => dispatch({ type: "increment" })}>+</button>
<button onClick={() => dispatch({ type: "set", payload: 100 })}>100</button>
{/* dispatch({ type: "set" }) — payload talab qilinadi (type-safe) */}
</div>
);
}Misol 6 — Event turlari (2.8)
function Form() {
const [value, setValue] = useState("");
// Alohida funksiya — qo'lda tur
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
setValue(e.target.value);
}
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
console.log(value);
}
return (
<form onSubmit={handleSubmit}>
<input value={value} onChange={handleChange} />
{/* Inline — TS o'zi anglaydi (qo'lda tur kerak emas): */}
<input onChange={(e) => setValue(e.target.value)} />
<button onClick={(e) => e.preventDefault()}>Yuborish</button>
</form>
);
}Misol 7 — Generic komponent: List (2.9)
interface ListProps<T> {
items: T[];
renderItem: (item: T) => React.ReactNode;
keyExtractor: (item: T) => string | number;
}
function List<T>({ items, renderItem, keyExtractor }: ListProps<T>) {
if (items.length === 0) return <p>Bo'sh</p>;
return <ul>{items.map(item => <li key={keyExtractor(item)}>{renderItem(item)}</li>)}</ul>;
}
// Ishlatish — TS turni anglaydi:
interface Product { id: string; name: string; price: number; }
<List<Product>
items={products}
renderItem={(p) => `${p.name} — ${p.price}`} // p: Product (autocomplete)
keyExtractor={(p) => p.id}
/>Misol 8 — Custom hook turi (2.10)
// Tuple qaytaruvchi (as const):
function useToggle(initial = false) {
const [on, setOn] = useState(initial);
const toggle = useCallback(() => setOn(o => !o), []);
return [on, toggle] as const; // [boolean, () => void] (tuple)
}
const [isOpen, toggle] = useToggle(); // isOpen: boolean, toggle: () => void
// Generic obyekt qaytaruvchi:
interface FetchResult<T> { data: T | null; loading: boolean; error: string | null; }
function useFetch<T>(url: string): FetchResult<T> {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
fetch(url).then(r => r.json()).then((d: T) => { setData(d); setLoading(false); });
}, [url]);
return { data, loading, error };
}
const { data } = useFetch<Product[]>("/api/products"); // data: Product[] | nullMisol 9 — HTML element props kengaytirish (2.12)
// Custom Input — <input>'ning BARCHA props'i + o'zimizniki:
interface InputProps extends React.ComponentProps<"input"> {
label: string;
error?: string;
}
function Input({ label, error, ...rest }: InputProps) {
return (
<div className="field">
<label>{label}</label>
<input {...rest} aria-invalid={!!error} /> {/* native props: onChange, placeholder, disabled... */}
{error && <span className="error">{error}</span>}
</div>
);
}
// Ishlatish — native input props avtomatik:
<Input label="Email" type="email" placeholder="email@x.uz" onChange={(e) => {}} required />
// onChange/type/placeholder/required — ComponentProps<"input">'dan (qo'lda yozMASDAN — 2.12)Misol 10 — Utility types: Omit, Partial (2.12)
interface User { id: string; name: string; email: string; password: string; role: "user" | "admin"; }
// Yangi user yaratish — id yo'q (server beradi), password kerak:
type CreateUserDto = Omit<User, "id">; // id'siz
// Tahrirlash — barcha maydon ixtiyoriy (faqat o'zgarganini yubor):
type UpdateUserDto = Partial<Omit<User, "id" | "password">>; // id/password'siz, hammasi ixtiyoriy
// Public user — parolsiz (xavfsizlik):
type PublicUser = Omit<User, "password">;
function updateUser(id: string, data: UpdateUserDto) { /* ... */ }
updateUser("1", { name: "Yangi" }); // faqat name (Partial — ixtiyoriy)Misol 11 — Context turi (2.13)
interface User { id: string; name: string; }
interface AuthContextType {
user: User | null;
login: (email: string, password: string) => Promise<void>;
logout: () => void;
}
const AuthContext = createContext<AuthContextType | null>(null); // null boshlang'ich
export function AuthProvider({ children }: React.PropsWithChildren) {
const [user, setUser] = useState<User | null>(null);
const login = async (email: string, password: string) => { /* ... */ setUser({ id: "1", name: "Ali" }); };
const logout = () => setUser(null);
return <AuthContext.Provider value={{ user, login, logout }}>{children}</AuthContext.Provider>;
}
export function useAuth(): AuthContextType {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error("useAuth AuthProvider ichida ishlatilishi kerak"); // null tekshiruv
return ctx; // tur: AuthContextType
}Misol 12 — Discriminated union props (2.7, 7.4)
// Komponent ikki rejimda — TS to'g'ri props'ni talab qiladi:
type AlertProps =
| { variant: "success"; message: string }
| { variant: "error"; message: string; retry: () => void }; // error'da retry MAJBURIY
function Alert(props: AlertProps) {
return (
<div className={`alert alert-${props.variant}`}>
<p>{props.message}</p>
{props.variant === "error" && <button onClick={props.retry}>Qayta</button>} {/* retry — faqat error'da */}
</div>
);
}
<Alert variant="success" message="Saqlandi" /> //
<Alert variant="error" message="Xato" retry={() => {}} /> //
// <Alert variant="error" message="Xato" /> // retry yetishmaydiMisol 13 — Zod + TS (sxema tur — 2.13)
import { z } from "zod";
const productSchema = z.object({
id: z.string(),
name: z.string(),
price: z.number().positive(),
inStock: z.boolean(),
});
type Product = z.infer<typeof productSchema>; // sxemadan tur (qo'lda interface yo'q)
const productsSchema = z.array(productSchema);
async function getProducts(): Promise<Product[]> {
const res = await fetch("/api/products");
const data = await res.json();
return productsSchema.parse(data); // runtime tekshiruv + tur (xato bo'lsa throw)
}
// z.infer — bir manba (validatsiya + tur); parse — server javobini xavfsiz qiladi (5.9, 11.10)Misol 14 — To'liq type-safe komponent (hammasi birga)
import { z } from "zod";
const userSchema = z.object({ id: z.string(), name: z.string(), role: z.enum(["user", "admin"]) });
type User = z.infer<typeof userSchema>;
interface UserCardProps extends React.ComponentProps<"div"> { // div props + o'zimizniki
user: User;
onSelect?: (id: string) => void;
}
function UserCard({ user, onSelect, ...rest }: UserCardProps) {
const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
onSelect?.(user.id);
};
return (
<div {...rest} className="user-card" onClick={handleClick}>
<h3>{user.name}</h3>
<span className={`badge badge-${user.role}`}>{user.role}</span> {/* role: "user"|"admin" */}
</div>
);
}
// Generic ro'yxat bilan birga:
function UserList({ users }: { users: User[] }) {
return (
<List<User>
items={users}
renderItem={(u) => <UserCard user={u} onSelect={(id) => console.log(id)} />}
keyExtractor={(u) => u.id}
/>
);
}
// Zod (tur) + interface (props) + ComponentProps (native) + event tur + generic — to'liq type-safeMisol 15 — forwardRef va ComponentProps (2.15, 2.14)
interface InputProps {
label: string;
error?: string;
}
// forwardRef<ref turi, props turi> — ref uzatuvchi komponent:
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ label, error }, ref) => (
<div className="field">
<label>{label}</label>
<input ref={ref} aria-invalid={!!error} /> {/* ref shu <input>'ga */}
{error && <span className="error">{error}</span>}
</div>
)
);
Input.displayName = "Input"; // devtools uchun (arrow — nom yo'q)
// Mavjud komponent props turini olish (qayta e'lon qilmasdan):
type InputPublicProps = React.ComponentProps<typeof Input>; // { label; error? } + ref
// Ishlatish — ref type-safe:
function Form() {
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => inputRef.current?.focus(), []); // ref.current: HTMLInputElement | null
return <Input ref={inputRef} label="Email" />;
}
// React 19'da forwardRef kerak emas (ref oddiy prop) — React 18'da esa shu naqsh (2.15)Misol 16 — Polymorphic komponent: as prop (2.16)
// To'liq type-safe polymorphic Box — as teg'ning native props'ini ham oladi:
type PolymorphicProps<E extends React.ElementType> = {
as?: E;
children?: React.ReactNode;
} & Omit<React.ComponentPropsWithoutRef<E>, "as" | "children">;
function Box<E extends React.ElementType = "div">({ as, children, ...rest }: PolymorphicProps<E>) {
const Component = as || "div";
return <Component {...rest}>{children}</Component>;
}
// Ishlatish — as teg'ga qarab native props type-safe:
<Box>oddiy div</Box> // <div>
<Box as="a" href="/uz">Havola</Box> // href — <a>'da bor
<Box as="button" type="submit" onClick={() => {}}>Yuborish</Box> // type/onClick — <button>'da
// <Box as="button" href="/x" /> // href <button>'da yo'q (type-safe)Misol 17 — Record props: i18n label'lar (2.14)
type Lang = "uz" | "en";
interface LabeledProps {
lang: Lang;
// Record<K, V> — har til uchun matn MAJBURIY (biror til yo'q bo'lsa — compile xatosi):
labels: Record<Lang, string>;
styles?: Record<string, string>; // ixtiyoriy kalitlar (inline CSS obyekti)
}
function Labeled({ lang, labels, styles }: LabeledProps) {
return <span style={styles}>{labels[lang]}</span>; // labels[lang] — string (type-safe)
}
<Labeled
lang="uz"
labels={{ uz: "Saqlash", en: "Save" }} // ikki til ham majburiy
styles={{ color: "red", fontWeight: "bold" }}
/>
// <Labeled lang="uz" labels={{ uz: "Saqlash" }} /> // "en" yetishmaydi (Record<Lang>)5. To'g'ri va noto'g'ri holatlar
1) Props turi
function C(props) {...} (any — TS himoyasi yo'q)
function C({ name }: Props) {...} (interface — type-safe — 2.3)2) useState null/bo'sh
const [user, setUser] = useState(null); (tur: null — setUser(realUser) xato)
useState<User | null>(null) (generic — 2.5)3) any ishlatish
const data: any = await res.json(); (TS himoyasi o'chadi — 2.17)
Zod parse yoki aniq tur (unknown + tekshiruv — 2.13, 7.5)4) React.FC
const C: React.FC<Props> = ... (eski, ortiqcha — 2.11)
function C({ ... }: Props) {...} (to'g'ridan props turi)5) Event turi
function h(e: any) {...} (e.target.value — any, himoya yo'q)
e: React.ChangeEvent<HTMLInputElement> (2.8)6) Custom hook tuple
return [on, toggle] (tur: (boolean | fn)[] — destructuring noto'g'ri)
return [on, toggle] as const (tuple — 2.10)6. Keng tarqalgan xatolar va yechimlari
Xato 1 — Type 'null' is not assignable to type 'User'
Sababi: useState(null) — tur null deb anglandi, keyin setUser(realUser) xato 2.5-bob. Yechimi: useState<User | null>(null).
Xato 2 — Object is possibly 'null' (ref/context)
Sababi: ref.current yoki context null bo'lishi mumkin (strict mode — 2.6, 2.13). Yechimi: ref.current?.focus() (optional chaining), yoki context'da if (!ctx) throw.
Xato 3 — Property 'value' does not exist on type 'EventTarget'
Sababi: event turi noto'g'ri yoki yo'q 2.8-bob. Yechimi: e: React.ChangeEvent<HTMLInputElement> (element turini bering).
Xato 4 — Custom hook destructuring noto'g'ri tur
Sababi: return [a, b] — massiv (tuple emas — 2.10). Yechimi: return [a, b] as const.
Xato 5 — Parameter 'item' implicitly has an 'any' type
Sababi: generic komponent turi berilmagan, yoki noImplicitAny (2.9, strict). Yechimi: generic tur (List<T>), yoki argument turi bering.
Xato 6 — Props'ga className/onClick berib bo'lmaydi (custom komponent)
Sababi: props turi native HTML props'ni qamramaydi 2.12-bob. Yechimi: extends React.ComponentProps<"div"> (yoki mos element).
Xato 7 — any orqali xato yashirin o'tib ketdi
Sababi: any TypeScript himoyasini o'chiradi 2.17-bob. Yechimi: unknown + tekshiruv, yoki aniq tur, yoki Zod parse.
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- TypeScript (7-QISM): turlar, interface, generics, utility types — React'da qo'llanadi.
- Komponent/props 11.2-bob: props turi — komponent shartnomasi.
- Hooks (11.5, 11.6): useState/useRef/useReducer turlari (generic, union).
- Forma + Zod 11.10-bob: z.infer — sxemadan tur (type-safe forma).
- Context 11.5-bob: createContext
+ null tekshiruv (11.7 hook bilan). - Backend 5.9-bob: bir xil Zod schema — full-stack type-safe.
- Custom hooks 11.7-bob: generic hook — type-safe qaytarish.
- API qatlami 12.4-bob: TanStack Query — generic, type-safe ma'lumot.
8. Eng yaxshi amaliyotlar (best practices)
strict: true(barcha TS himoyasi — eng muhim sozlama — 2.2).- Props interface/type (har komponentga — autocomplete + tekshiruv — 2.3).
any'dan qoch (unknown+ tekshiruv, aniq tur, Zod — 2.17, 7.5).- Inference'ga ishon (oddiy useState/event — qo'lda tur yozma — 2.5, 2.8).
- Generic null/bo'sh state'ga (
useState<T|null>,useState<T[]>— 2.5). as consttuple hook'da (return [a, b] as const— 2.10).ComponentProps<"el">native HTML props meros qilishda 2.12-bob.z.inferZod bilan (sxema tur — bir manba — 2.13).- Context null tekshiruv (
createContext<T|null>+ hook throw — 2.13). React.FCemas, props turi (to'g'ridan — soddaroq — 2.11).- Qaytarish turini yozmang (inference —
JSX.Element/ReactNodeqo'lda kamdan-kam — 2.14). ComponentProps<typeof X>mavjud komponent props'ini olishda (DRY — 2.14).forwardRef<El, Props>+displayNameref uzatuvchi komponentda 2.15-bob.- Polymorphic
asprop dizayn-tizim komponentlarida (ElementType— 2.16).
9. Amaliy loyiha: "JavaScript loyihani TypeScript'ga ko'chirish"
Mavjud (yoki yangi) React loyihani to'liq type-safe qilib, TypeScript afzalliklarini amalda his qilish.
Maqsad
Kichik React ilovani (oldingi loyihalardan biri) TypeScript'ga ko'chiring yoki noldan TS bilan yozing — har qatlamni (komponent, hook, Context, API) type-safe qiling.
Talablar (requirements)
- Setup:
react-tsshablon yoki mavjud loyihani.tsxga ko'chiring,strict: true2.2-bob. - Props turlari: har komponentga
interface/type(union, optional — Misol 1, 2.3). - children: o'rovchi komponentlarga
React.ReactNode/PropsWithChildren(Misol 2, 2.4). - Hooklar:
useStategeneric (null/massiv),useRefDOM,useReducerdiscriminated union (Misol 3-5). - Event: handler'larga to'g'ri event turi (Misol 6, 2.8).
- Generic komponent: kamida bitta (List/Table/Select — Misol 7, 2.9).
- Custom hook: type-safe (tuple
as constyoki generic — Misol 8, 2.10). - HTML props: kamida bitta komponent
ComponentProps<"el">bilan kengaytirsin (Misol 9, 2.12). - Context:
createContext<T|null>+ null tekshiruvli hook (Misol 11, 2.13). - Zod: API qatlamida
z.infer+parse(type-safe + runtime — Misol 13, 2.13).
Maslahatlar (hint)
strict: trueni yoq — usiz TS'ning yarim foydasi yo'qoladi 2.2-bob.anydan qoch — agar bilmasangizunknown+ tekshiruv (Xato 7).- Inference'ga ishon: oddiy
useState(0)/inline event — qo'lda tur yozma (2.5, 2.8). - null/bo'sh state — generic kerak (
useState<User|null>(null)— Xato 1). React.FCishlatma — to'g'ridan props turi 2.11-bob.- Zod sxemani backend bilan ulashishga tayyorla (bir manba — 5.9, 11.10).
"Tayyor" mezonlari (acceptance criteria)
-
strict: true, hech qandayanyyo'q (yoki oqlangan). - Har komponent props turlangan.
- children turlari to'g'ri (ReactNode).
- Hooklar turlangan (generic null/massiv, discriminated union reducer).
- Event handler'lar turlangan.
- Generic komponent ishlaydi (type-safe).
- Custom hook type-safe (tuple/generic).
- Context null tekshiruvli hook bilan.
- Zod API chegarasida (parse + infer).
- Muharrir hech qanday TS xato ko'rsatmaydi (compile toza).
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda TypeScript va React birikmasini chuqur o'rgandik:
- Nega TS (xato erta, autocomplete, refactoring — 2.1); setup (react-ts, strict — 2.2); props turlari 2.3-bob; children (ReactNode — 2.4).
- Hooklar turlari (useState generic — 2.5, useRef — 2.6, useReducer discriminated union — 2.7); event turlari 2.8-bob; generic komponentlar 2.9-bob; custom hook 2.10-bob.
- React.FC munozarasi 2.11-bob; utility types (ComponentProps, Omit, Partial — 2.12); Context va Zod 2.13-bob; JSX.Element vs ReactNode, ComponentProps
, Record 2.14-bob; forwardRef 2.15-bob; polymorphic komponent (as, ElementType — 2.16); type-safe tafakkur 2.17-bob.
Endi siz komponentdan API qatlamigacha (va backend'gacha — Zod) to'liq type-safe React ilova yoza olasiz — xatolar compile paytida tutiladi, autocomplete tezligini oshiradi, refactoring xavfsiz. Bu — 2026 professional React loyihasining standarti.
Keyingi bob — 11.15-bob: Dashboard loyiha — layout, auth. Endi shu paytgacha o'rgangan barcha narsalarni (komponent, hooklar, routing, forma, performance, TypeScript) bitta real loyihada birlashtiramiz: professional dashboard. Layout pattern (sidebar + header + Outlet), responsive (mobil sidebar), autentifikatsiya oqimi (login token protected routes), API qatlami (axios instance + interceptors), CRUD sahifa naqshi, va production tayyorlik (error boundary + lazy + a11y). Bu — sizning portfoliongning markaziy loyihasi bo'lishi mumkin.
Foydalanilgan rasmiy/ishonchli manbalar
- React rasmiy hujjati — "Using TypeScript" bo'limi: komponent va hook turlari,
ReactNode, event turlari, Context tiplash. - TypeScript rasmiy hujjati — utility types (
Partial,Pick,Omit,Record), generics, discriminated union,as const, type vs interface. - React + TypeScript Cheatsheet (jamoaviy ochiq qo'llanma) — props naqshlari,
forwardRef, polymorphic komponent,ComponentProps/ComponentPropsWithoutRef. - Vite rasmiy hujjati —
react-tsshabloni va loyiha sozlamalari (tsconfig,strict). - Zod rasmiy hujjati — sxema,
z.infer,parse/safeParse(API chegarasida runtime validatsiya). - DefinitelyTyped (
@types) — kutubxonalar uchun tur ta'riflari (@types/react,@types/node).
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!