TypeScript para React: Guia Prático 2026
Domine TypeScript em projetos React com exemplos práticos. Tipagem de props, hooks, eventos, API responses, generics e patterns que devs seniores usam.
Por que isso é importante
TypeScript para React: Guia Prático 2026. Domine TypeScript em projetos React com exemplos práticos. Tipagem de props, hooks, eventos, API responses, generics e patterns que devs seniores usam.
TypeScript em 5 Minutos
TypeScript é JavaScript com tipos. Todo código JavaScript válido já é TypeScript válido. Você adiciona tipos gradualmente: comece com props de componentes, depois hooks, depois API responses. Não precisa tipar tudo no dia 1.
Setup rápido
npx create-next-app@latest --typescript já configura tudo. Para projetos existentes: npm install -D typescript @types/react @types/node e renomeie .jsx para .tsx. O compilador infere tipos automaticamente na maioria dos casos.
Tipando Props de Componentes
Props são o contrato entre componentes. TypeScript garante que quem usa o componente passa os dados corretos. Erros aparecem no editor, não em produção.
interface ButtonProps { label: string; onClick: () => void; disabled?: boolean; }. O ? marca props opcionais.children: React.ReactNode para aceitar qualquer JSX. React.ReactElement se quiser apenas elementos React (sem strings).variant: "primary" | "secondary" | "ghost". O editor mostra as opções válidas no autocompletar. Erro se passar valor inválido.interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>. Herda todas as props de um button HTML (onClick, disabled, type, etc.) e adiciona as suas.Interface vs Type
Use interface para props de componentes (extensível, mergeável). Use type para unions, intersections e tipos computados. Na prática, ambos funcionam em 95% dos casos. A convenção React é interface para props.
Tipando Hooks
useState
TypeScript infere o tipo do valor inicial. useState(0) é automaticamente number. Para tipos complexos ou inicialização com null, declare explicitamente: useState<User | null>(null).
const [count, setCount] = useState(0) — TypeScript sabe que count é number e setCount aceita number.const [user, setUser] = useState<User | null>(null) — necessário quando o tipo muda (null → User após fetch).const [items, setItems] = useState<Product[]>([]) — array vazio não infere o tipo dos elementos, declare explicitamente.useRef
Para refs DOM: useRef<HTMLInputElement>(null). O tipo garante que ref.current tem as propriedades corretas (value, focus, etc.). Para valores mutáveis: useRef<number>(0).
useReducer
Discriminated unions brilham aqui. Defina cada action como tipo separado: type Action = { type: "increment" } | { type: "set"; payload: number }. O TypeScript garante que payload só existe quando type === "set". Switch no reducer tem autocomplete e exaustividade.
Tipando Eventos
Eventos no React têm tipos específicos. O padrão: React.[Evento]Event<HTMLElemento>.
React.MouseEvent<HTMLButtonElement>. Acesse e.currentTarget para o elemento que disparou.React.ChangeEvent<HTMLInputElement>. O e.target.value é tipado como string automaticamente.React.FormEvent<HTMLFormElement>. Chame e.preventDefault() e extraia dados com FormData.React.KeyboardEvent<HTMLInputElement>. Use e.key === "Enter" para detectar teclas específicas.Tipando API Responses
Dados de API são o ponto mais vulnerável. Sem tipos, um campo renomeado no backend quebra o frontend silenciosamente. Com TypeScript + Zod, a validação acontece em runtime e compilação.
interface User { id: string; name: string; email: string; }. Aplique no fetch: const data: User[] = await res.json().type User = z.infer<typeof userSchema>. Um único source of truth para tipo e validação.async function fetchApi<T>(url: string): Promise<T>. Reutilize em qualquer endpoint com tipo específico.type ApiResponse<T> = { success: true; data: T } | { success: false; error: string }. O TypeScript força check de success antes de acessar data.Generics: O Superpoder do TypeScript
Generics criam componentes e funções que funcionam com qualquer tipo mantendo type safety. É como um parâmetro, mas para tipos em vez de valores.
function List<T>({ items, renderItem }: { items: T[]; renderItem: (item: T) => ReactNode }). Funciona com User[], Product[], qualquer tipo. O caller define T implicitamente.function useFetch<T>(url: string): { data: T | null; loading: boolean; error: string | null }. O tipo retornado acompanha o genérico.<T extends { id: string }> garante que T tem propriedade id. Restringe o genérico sem perder flexibilidade.Utility Types Essenciais
TypeScript inclui tipos utilitários que transformam tipos existentes. Evitam duplicação e mantêm tipos sincronizados.
function updateUser(id: string, data: Partial<User>). Permite enviar apenas os campos que mudaram.Pick<User, "name" | "email"> cria tipo com apenas name e email. Ideal para formulários parciais.Omit<User, "id" | "createdAt"> para formulários de criação que não precisam de id.Record<string, number> para dicionários. Record<Status, Color> para mapas de configuração.ReturnType<typeof getUser> mantém tipos sincronizados com a implementação sem duplicar.Patterns Avançados para React
type Props = { variant: "link"; href: string } | { variant: "button"; onClick: () => void }. Props mudam baseado no variant. TypeScript garante que href só existe quando variant é "link".as prop para mudar o elemento renderizado. Button que pode ser <a> ou <button> com tipos corretos para cada um.createStrictContext<T>() que retorna erro se usado fora do Provider ao invés de retornar undefined. Elimina null checks em consumers.{ params: { slug: string } } garante que a página recebe o parâmetro esperado.TypeScript com Next.js
Next.js tem suporte first-class para TypeScript. Tipos para pages, layouts, API routes e metadata são gerados automaticamente.
Tipos Next.js essenciais
Metadata: import type { Metadata } from "next" para tipar metadata estática.
Route params: { params: Promise<{ slug: string }> } no Next.js 15+ (params é async).
Server Actions: Tipo do FormData e retorno são inferidos. Use Zod para validar inputs.
API Routes: NextRequest e NextResponse do next/server.
Checklist TypeScript + React
Conclusão
TypeScript não é overhead — é investimento. O tempo gasto tipando é recuperado 10x em bugs prevenidos, refactors seguros e onboarding rápido de novos devs. Comece tipando props e API responses. Em 2 semanas, você não imagina voltar para JavaScript puro.