Skip to main content

Як типізувати стан за допомогою useState()?

Базові випадки

javascript
// Type inferred from the literal const [count, setCount] = useState(0); // number const [title, setTitle] = useState("Hello"); // string const [open, setOpen] = useState(false); // boolean

Коли потрібно вказати тип явно:

  • початкове значення null / undefined;
  • складні об'єднання (union), об'єкти, масиви;
  • хочеш звузити тип (наприклад, літеральні типи).
javascript
// Explicit typing with null const [user, setUser] = useState<User | null>(null); // Union type Status = "idle" | "loading" | "success" | "error"; const [status, setStatus] = useState<Status>("idle"); // Literal variants const [variant, setVariant] = useState<"primary" | "ghost">("primary");

Об'єкти та часткові оновлення

javascript
type Form = { name: string; age: number }; const [form, setForm] = useState<Form>({ name: "", age: 0 }); // Update based on the previous state setForm(prev => ({ ...prev, name: "Tim" }));

Поради • Тип у prev виводиться автоматично. • Для багатокрокових форм і складної логіки розглянь useReducer.


Масиви та колекції

javascript
const [items, setItems] = useState<string[]>([]); // Adding an item setItems(prev => [...prev, "new"]); // Set/Map (mutable!) - create new instances const [ids, setIds] = useState<Set<string>>(new Set()); setIds(prev => new Set(prev).add("42"));

Nullable / Optional правильно

javascript
// Better: an explicit union with null const [el, setEl] = useState<HTMLDivElement | null>(null); // Same with undefined const [token, setToken] = useState<string | undefined>(undefined);

Не використовуй «абияк» через as any - це ламає гарантії TS.


Лінивий ініціалізатор (для дорогих обчислень)

javascript
const [big, setBig] = useState<number>(() => heavyCompute()); // The function runs once, on mount.

Похідні типи та «вузькі» літерали

javascript
// From API types type User = ApiUser & { fullName: string }; // A narrow literal via a const assertion const [align, setAlign] = useState<"left" | "center" | "right">("left"); // Or derive it from a settings object: const ALIGN = ["left", "center", "right"] as const; type Align = (typeof ALIGN)[number]; const [a, setA] = useState<Align>("left");

Стан запиту (дискриміновані union)

javascript
type LoadState = | { status: "idle" } | { status: "loading" } | { status: "success"; data: Post[] } | { status: "error"; error: string }; const [state, setState] = useState<LoadState>({ status: "idle" }); setState({ status: "loading" }); // ... setState({ status: "success", data });

Зручно для вичерпних switch без «default».


Типи сетера та функцій оновлення

javascript
const [n, setN] = useState(0); // Type: React.Dispatch<React.SetStateAction<number>> // You can pass a function that receives prev setN(prev => prev + 1);

Контрольовані інпути

javascript
const [value, setValue] = useState(""); const onChange = (e: React.ChangeEvent<HTMLInputElement>) => setValue(e.target.value);

Коли явно вказувати дженерик

Вказуй <T>, якщо:

  • початкове значення null/undefined;
  • масиви/об'єкти/union;
  • хочеш «зафіксувати» точний тип (наприклад, string vs string | undefined).

Приклади коротко:

javascript
// good const [data, setData] = useState<Post[] | null>(null); // good const [map, setMap] = useState<Map<string, number>>(new Map()); // good const [mode, setMode] = useState<"view" | "edit">("view"); // bad - too broad, any const [unknown, setUnknown] = useState<any>(null);

Часті помилки і як їх уникнути

  • Ініціалізація useState(null) без типу -> стане null, і далі TS скаржиться. Виправлення: useState<User | null>(null)
  • Мутування складних структур (Set/Map, об'єкти) -> React не побачить зміну. Виправлення: створюй нову структуру.
  • Стан, зав'язаний на безліч гілок -> заплутаний union. Виправлення: подумай про useReducer.

Підсумок

  1. Довіряй виведенню типів, але задавай <T> при null/undefined і складних формах.
  2. Для об'єктів і масивів - іммутабельні оновлення.
  3. Для сценаріїв завантаження - дискриміновані union.
  4. Не бійся лінивого ініціалізатора та літеральних типів - це робить стан точним і надійним.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.