eduardweb.
React & TypeScriptÎncepător#typescript#react#frontend#erori-frecvente

React cu TypeScript strict: 5 erori de care te lovești garantat la început

De Bogdan Răducanu, 5 sept. 2026 · 19 vizualizări · 2 like-uri

Postat 5 sept. 2026
typescript
import { useState, useRef, ChangeEvent, FormEvent } from 'react';

interface User {
  id: number;
  name: string;
}

export const UserForm = () => {
  // 1. useState cu generic corect (fără never[])
  const [users, setUsers] = useState<User[]>([]);
  const [name, setName] = useState('');
  
  // 2. useRef inițializat explicit
  const inputRef = useRef<HTMLInputElement>(null);

  // 3. Tipare corectă pentru onChange
  const handleNameChange = (e: ChangeEvent<HTMLInputElement>) => {
    setName(e.target.value);
  };

  // 4. Tipare corectă pentru onSubmit
  const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    if (!name.trim()) return;

    setUsers((prev) => [...prev, { id: Date.now(), name }]);
    setName('');
    
    // Optional chaining în loc de non-null assertion (!)
    inputRef.current?.focus();
  };

  return (
    <form onSubmit={handleSubmit}>
      <input ref={inputRef} value={name} onChange={handleNameChange} />
      <button type="submit">Adaugă</button>
    </form>
  );
};

Când am activat prima dată "strict": true pe un proiect de React existent — un dashboard intern cu vreo 8k utilizatori activi — consola mea a explodat cu 140 de erori. Impulsul inițial a fost să pun // @ts-ignore peste tot sau să trântesc any, doar ca să treacă pipeline-ul de CI/CD.

E o greșeală clasică. Dacă știi exact de ce urlă compilatorul, majoritatea erorilor se rezolvă în câteva secunde.

1. useState([]) inițializat ca never[]

Scrii const [items, setItems] = useState([]); și două rânduri mai jos vrei să faci items.push(...) sau să accesezi items[0].id. Bum: Property 'id' does not exist on type 'never'.

TypeScript deduce tipul pe baza valorii inițiale. Pentru un array gol fără context, el deduce never[], adică o listă care nu poate conține niciodată nimic. Rezolvarea e să-i dai explicit generic-ul: useState<User[]>([]).

2. Evenimente de input netipate corect

La un simplu onChange, dacă lași parametrul e fără tip, TS strict aruncă Parameter 'e' implicitly has an 'any' type. Mulți pun e: any și merg mai departe, pierzând autocompletion-ul.

Soluția corectă este să folosești tipurile native din React: React.ChangeEvent<HTMLInputElement>. Dacă e pe form, ai React.FormEvent<HTMLFormElement>. Îți ia trei secunde să-l scrii și ai acces instant la e.currentTarget.value fără dubii.

3. Object is possibly 'null' la useRef

Când declari const inputRef = useRef<HTMLInputElement>(null);, TypeScript te obligă pe bună dreptate să verifici existența nodului din DOM înainte să-l accesezi. Dacă scrii direct inputRef.current.focus(), codul pică la compilare.

Soluția nu e operatorul ! de non-null assertion (inputRef.current!.focus()), deși îl văd des. Soluția sănătoasă e un simplu optional chaining: inputRef.current?.focus(). Dacă ref-ul nu e încă atașat, aplicația nu crapă în runtime.

4. Props opționale cu valori undefined

Dacă ai un prop marcat cu semnul întrebării (title?: string), iar componenta ta îl trimite mai departe într-o funcție care cere strict string, primești Type 'undefined' is not assignable to type 'string'.

În loc să faci casting forțat, rezolvă problema din destructurare cu o valoare default: const { title = 'Titlu implicit' } = props;. Din momentul ăla, TS știe sigur că title e garantat string în interiorul componentei.

5. Destructurarea proprietăților necunoscute

Când preiei date dintr-un API extern și le definești sumar, iar apoi încerci să accesezi o proprietate dinamică, TS se blochează dacă nu ai un index signature. În loc de Record<string, any>, recomand să folosești Record<string, unknown> combinat cu type guards simple sau biblioteci de validare la runtime gen Zod.

Merită efortul?

Strict mode te încetinește cu vreo 20-30% în primele zile când scrii cod, nu te mint. Dar la proiectul de care ziceam, numărul de bug-uri legate de date lipsă raportate în Sentry a scăzut aproape la zero după refactorizare. Nu mai ai surprize cu Cannot read properties of undefined în producție.

Voi cum ați făcut tranziția: ați pornit din start cu strict sau ați migrat treptat fișierele?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.