Pular para o conteúdo
TypeScript

Tipar Eventos no React com TypeScript

Cansado de colocar 'any' nos event handlers? Aqui voce aprende a tipar onClick, onChange, onSubmit e todos os eventos do React com TypeScript de uma vez.

Por que isso é importante

Tipar Eventos no React com TypeScript. Cansado de colocar 'any' nos event handlers? Aqui voce aprende a tipar onClick, onChange, onSubmit e todos os eventos do React com TypeScript de uma vez.

Como funciona o sistema de eventos do React com TypeScript

O React nao usa eventos nativos do DOM direto. Ele envolve tudo em SyntheticEvent, um wrapper cross-browser que tem a mesma interface dos eventos nativos mas funciona de forma padronizada. O TypeScript tem tipos especificos pra cada variante: ChangeEvent, MouseEvent, FormEvent, KeyboardEvent, FocusEvent, DragEvent e por ai vai.

Cada tipo de evento aceita um generico que define qual elemento HTML disparou o evento. Isso e o pulo do gato: quando voce diz React.ChangeEvent, o TypeScript sabe que event.target e um input e te da acesso a .value, .checked, .name e todas as propriedades de input.

// Hierarquia de tipos de evento no React
SyntheticEvent          // Base de todos
├── ChangeEvent         // onChange
├── MouseEvent          // onClick, onMouseEnter, etc.
├── FormEvent           // onSubmit
├── KeyboardEvent       // onKeyDown, onKeyUp, onKeyPress
├── FocusEvent          // onFocus, onBlur
├── DragEvent           // onDrag, onDrop
├── ClipboardEvent      // onCopy, onPaste
├── TouchEvent          // onTouchStart, onTouchEnd
├── WheelEvent          // onWheel
└── AnimationEvent      // onAnimationStart, onAnimationEnd

// Generico define o elemento HTML
React.ChangeEvent<HTMLInputElement>
React.MouseEvent<HTMLButtonElement>
React.FormEvent<HTMLFormElement>

Passo a passo: tipando eventos no React

  1. Identifique qual evento voce esta usando (onClick, onChange, onSubmit, etc.)
  2. Escolha o tipo React correto: MouseEvent, ChangeEvent, FormEvent, etc.
  3. Passe o elemento HTML como generico: ,
  4. Use o tipo no parametro da funcao handler
  5. Acesse event.target com autocomplete completo e sem erros
  6. Para handlers passados como props, use React.EventHandler ou os tipos de handler especificos

Exemplos praticos de cada tipo de evento

ChangeEvent: inputs, selects e textareas

O evento mais usado no dia a dia. Cada tipo de input precisa do elemento HTML correto no generico. Olha a diferenca:

import React, { useState } from 'react';

function FormExample() {
  const [name, setName] = useState('');
  const [age, setAge] = useState(0);
  const [bio, setBio] = useState('');
  const [role, setRole] = useState('dev');
  const [agreed, setAgreed] = useState(false);

  // Input de texto
  const handleName = (e: React.ChangeEvent<HTMLInputElement>) => {
    setName(e.target.value); // .value e string
  };

  // Input numerico
  const handleAge = (e: React.ChangeEvent<HTMLInputElement>) => {
    setAge(Number(e.target.value));
  };

  // Textarea
  const handleBio = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
    setBio(e.target.value);
  };

  // Select
  const handleRole = (e: React.ChangeEvent<HTMLSelectElement>) => {
    setRole(e.target.value);
  };

  // Checkbox
  const handleAgreed = (e: React.ChangeEvent<HTMLInputElement>) => {
    setAgreed(e.target.checked); // .checked e boolean
  };

  return (
    <form>
      <input type="text" value={name} />
      <input type="number" value={age} />
      <textarea value={bio} />
      <select value={role}
        <option value="dev">Dev</option>
        <option value="designer">Designer</option>
      </select>
      <input type="checkbox" checked={agreed} />
    </form>
  );
}

MouseEvent: clicks e interacoes de mouse

MouseEvent te da acesso a coordenadas do clique, qual botao foi pressionado e se teclas modificadoras (Ctrl, Shift) estavam ativas. Super util pra menus contextuais e interacoes avancadas.

import React from 'react';

function InteractiveArea() {
  // Click em botao
  const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
    console.log('Coordenadas:', e.clientX, e.clientY);
    console.log('Ctrl pressionado:', e.ctrlKey);
  };

  // Click em div (menu contextual)
  const handleContextMenu = (e: React.MouseEvent<HTMLDivElement>) => {
    e.preventDefault();
    console.log('Menu em:', e.pageX, e.pageY);
  };

  // Mouse enter/leave
  const handleMouseEnter = (e: React.MouseEvent<HTMLDivElement>) => {
    const target = e.currentTarget; // tipo: HTMLDivElement
    target.style.backgroundColor = '#333';
  };

  return (
    <div
      <button aqui</button>
    </div>
  );
}

FormEvent e onSubmit

O FormEvent e o que voce usa no onSubmit. O detalhe importante: use e.currentTarget ao inves de e.target pra acessar os campos do formulario de forma tipada.

import React, { useState } from 'react';

interface LoginData {
  email: string;
  password: string;
}

function LoginForm() {
  const [formData, setFormData] = useState<LoginData>({
    email: '',
    password: '',
  });

  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    // Tipo seguro: formData ja e LoginData
    console.log('Login:', formData.email);
  };

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const { name, value } = e.target;
    setFormData(prev => ({ ...prev, [name]: value }));
  };

  return (
    <form
      <input name="email" type="email" />
      <input name="password" type="password" />
      <button type="submit">Entrar</button>
    </form>
  );
}

KeyboardEvent: atalhos de teclado

import React from 'react';

function SearchInput() {
  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault();
      console.log('Buscando...');
    }

    if (e.key === 'Escape') {
      (e.target as HTMLInputElement).blur();
    }

    // Atalho Ctrl+K
    if (e.ctrlKey && e.key === 'k') {
      e.preventDefault();
      console.log('Atalho de busca');
    }
  };

  return <input placeholder="Buscar..." />;
}

Event handlers como props

Quando voce precisa passar um handler como prop, existem dois jeitos de tipar. O React tem tipos de handler prontos que simplificam bastante:

// Jeito 1: tipo do handler completo
interface ButtonProps {
  onClick: (e: React.MouseEvent<HTMLButtonElement>) => void;
  onHover?: (e: React.MouseEvent<HTMLButtonElement>) => void;
}

// Jeito 2: tipos de handler do React (mais limpo)
interface ButtonProps2 {
  onClick: React.MouseEventHandler<HTMLButtonElement>;
  onHover?: React.MouseEventHandler<HTMLButtonElement>;
}

// Jeito 3: generico pra qualquer evento
interface InputProps {
  onChange: React.ChangeEventHandler<HTMLInputElement>;
  onFocus: React.FocusEventHandler<HTMLInputElement>;
  onKeyDown: React.KeyboardEventHandler<HTMLInputElement>;
}

function CustomButton({ onClick, onHover }: ButtonProps2) {
  return (
    <button
      Clique
    </button>
  );
}

Erros comuns ao tipar eventos

Armadilhas que pegam todo mundo

Confundir event.target com event.currentTarget e o erro numero 1. O target e o elemento que disparou o evento (pode ser um filho), enquanto currentTarget e o elemento onde o handler esta anexado. Outro erro classico: usar eventos nativos do DOM (Event, MouseEvent) ao inves dos tipos do React (React.MouseEvent). Sao tipos diferentes e nao sao intercambiaveis.

// ERRADO: tipo nativo do DOM ao inves do React
const handleClick = (e: MouseEvent) => {};
// Deveria ser: React.MouseEvent<HTMLButtonElement>

// ERRADO: generico errado no ChangeEvent
const handleChange = (e: React.ChangeEvent<HTMLButtonElement>) => {
  e.target.value; // Erro: HTMLButtonElement nao tem .value
};
// Deveria ser: React.ChangeEvent<HTMLInputElement>

// ERRADO: target vs currentTarget
const handleDiv = (e: React.MouseEvent<HTMLDivElement>) => {
  e.target; // tipo: EventTarget (generico demais!)
  e.currentTarget; // tipo: HTMLDivElement (correto!)
};

// CERTO: usar currentTarget quando precisa do elemento do handler
const handleDivCorreto = (e: React.MouseEvent<HTMLDivElement>) => {
  const element = e.currentTarget; // HTMLDivElement
  element.dataset.id; // funciona!
};

Checklist: eventos React tipados

Checklist Final

  • Usa React.ChangeEvent, React.MouseEvent (nao os tipos nativos do DOM)
  • Generico do evento corresponde ao elemento HTML correto
  • currentTarget usado quando precisa acessar o elemento do handler
  • Handlers como props usam React.EventHandler types
  • FormEvent usado no onSubmit com preventDefault
  • KeyboardEvent.key usado ao inves do depreciado keyCode
  • Nenhum 'any' nos parametros de event handlers
  • Checkbox usa e.target.checked, text usa e.target.value

Domine tipagem React no projeto real

Projeto completo com TypeScript

Tipar eventos e uma daquelas habilidades que voce usa todo dia no trabalho. No CrazyStack voce pratica isso construindo formularios reais, dashboards interativos e componentes reutilizaveis — tudo tipado de ponta a ponta com TypeScript, React e Node.js.