Daraja 9 β TypeScript bilan React¶
β¬ οΈ Oldingi: Daraja 8 β Advanced patterns Β· π README Β· Keyingi: Daraja 10 β Testing β‘οΈ
TypeScript β JavaScript'ga tip qo'shadi. Xatolarni yozish paytida topadi, refactoring'ni xavfsiz qiladi. 2026'da professional React = TypeScript.
9.1. Props'ni tiplash¶
type ButtonProps = {
label: string;
onClick: () => void;
variant?: "primary" | "secondary"; // ixtiyoriy
disabled?: boolean;
};
function Button({ label, onClick, variant = "primary", disabled }: ButtonProps) {
return (
<button className={variant} onClick={onClick} disabled={disabled}>
{label}
</button>
);
}
children bilan:
type CardProps = {
title: string;
children: React.ReactNode; // har qanday JSX
};
function Card({ title, children }: CardProps) {
return <div><h2>{title}</h2>{children}</div>;
}
9.2. Hook'larni tiplash¶
// useState β odatda tip o'zi aniqlanadi (inference)
const [count, setCount] = useState(0); // number
const [name, setName] = useState(""); // string
// Murakkab tip bo'lsa β aniq belgilang
const [user, setUser] = useState<User | null>(null);
type User = { id: number; name: string };
// useRef
const inputRef = useRef<HTMLInputElement>(null);
// useReducer
type State = { count: number };
type Action = { type: "inc" } | { type: "dec" } | { type: "set"; payload: number };
function reducer(state: State, action: Action): State {
switch (action.type) {
case "inc": return { count: state.count + 1 };
case "dec": return { count: state.count - 1 };
case "set": return { count: action.payload };
}
}
9.3. Event'larni tiplash¶
function Form() {
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
console.log(e.target.value);
};
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
};
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {};
}
9.4. Generic komponentlar¶
type ListProps<T> = {
items: T[];
renderItem: (item: T) => React.ReactNode;
};
function List<T>({ items, renderItem }: ListProps<T>) {
return <ul>{items.map((item, i) => <li key={i}>{renderItem(item)}</li>)}</ul>;
}
// Ishlatish β tip avtomatik aniqlanadi
<List items={users} renderItem={(u) => u.name} />
9.5. Custom hook'ni tiplash¶
function useToggle(initial = false): [boolean, () => void] {
const [value, setValue] = useState(initial);
const toggle = () => setValue((v) => !v);
return [value, toggle];
}
9.6. Foydali utility tiplar¶
React.ReactNodeβ har qanday renderlanadigan narsaReact.FC<Props>β function component (lekin hozir to'g'ridan-to'g'ri annotatsiya afzal)Partial<T>,Pick<T>,Omit<T>β tiplarni qayta shakllantirishComponentProps<"button">β HTML element propslarini olish
// Native button propslarini meros qilib olish
type Props = React.ComponentProps<"button"> & { variant: "primary" };
9.7. Keng tarqalgan xatolar¶
| Xato | To'g'risi |
|---|---|
any ishlatish |
Aniq tip bering yoki unknown |
React.FCni majburlash |
To'g'ridan-to'g'ri props annotatsiyasi |
| Event tipini noto'g'ri tanlash | ChangeEvent, MouseEvent, FormEvent |
useStatega tip bermaslik (null bo'lsa) |
useState<T \| null>(null) |
| API javobini tiplab olmaslik | Zod bilan runtime validatsiya + tip |
+20 Masala β Daraja 9¶
Oson:
1. Button komponentini TypeScript bilan tiplang.
2. Card (children bilan) tiplang.
3. useStateni User \| null bilan ishlating.
4. onChange event'ini to'g'ri tiplang.
5. Ixtiyoriy (?) va union tip ("a" \| "b") propslar yozing.
6. useRef<HTMLInputElement> bilan input fokus qiling.
7. Props tipini type orqali eksport qiling.
8. Mavjud JS komponentni TS'ga ko'chiring.
O'rta:
9. Generic List<T> komponenti yozing.
10. useReducerni to'liq tiplang (State + Action union).
11. useToggle custom hook'ini tiplang (tuple qaytarsin).
12. API javobini interface bilan tiplab, useQueryda ishlating.
13. Omit/Pick bilan tiplarni qayta ishlating.
14. ComponentProps<"input"> bilan native propslarni meros qiling.
15. Discriminated union bilan turli holatlarni tiplang (loading/success/error).
Qiyin:
16. To'liq todo ilovasini TypeScript bilan qayta yozing.
17. Generic useFetch<T> hook'i yozing.
18. Zod schema + TypeScript bilan type-safe forma.
19. Polymorphic komponent (as prop bilan har xil HTML element).
20. EduCore bir modulini (masalan, student ro'yxati) to'liq type-safe qiling.
β Qiyin masalalar yechimi (16β20)
16 β Typed todo (asosiy tip + state):
type Todo = { id: number; text: string; done: boolean };
function TodoApp() {
const [todos, setTodos] = useState<Todo[]>([]);
const add = (text: string) =>
setTodos((p) => [...p, { id: Date.now(), text, done: false }]);
// ...
}
17 β Generic useFetch<T> (ignore bilan race'dan himoya):
function useFetch<T>(url: string) {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
let ignore = false;
fetch(url)
.then((r) => r.json())
.then((d: T) => { if (!ignore) setData(d); })
.catch((e) => { if (!ignore) setError(e); })
.finally(() => { if (!ignore) setLoading(false); });
return () => { ignore = true; }; // race condition'dan himoya
}, [url]);
return { data, loading, error };
}
// const { data } = useFetch<Student[]>("/api/students"); // data: Student[] | null
19 β Polymorphic komponent (as prop):
import type { ElementType, ComponentPropsWithoutRef } from "react";
type TextProps<T extends ElementType> = {
as?: T;
children: React.ReactNode;
} & ComponentPropsWithoutRef<T>;
function Text<T extends ElementType = "span">({ as, children, ...rest }: TextProps<T>) {
const Component = as || "span";
return <Component {...rest}>{children}</Component>;
}
// <Text as="h1">Sarlavha</Text> yoki <Text as="a" href="/">Havola</Text> β props tipi `as`ga moslashadi
(18 β Zod + TS:
z.infer<typeof schema>bilan tipni schema'dan avtomatik olasan; 20 β EduCore moduli:Studenttipi +useFetch<Student[]>+ typed props birlashtirib.)