TypeScript Academy · Aula

emit e on com Segurança de Tipos

Garanta os dados associados corretos ao emitir eventos e escutá-los.

Aula 2 de 413 etapas

emit e on com Segurança de Tipos é uma aula grátis de TypeScript Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de TypeScript Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de TypeScript Academy inclui 4 aulas no total.

Uma assinatura de emit com segurança de tipos

Torne emit genérico em relação ao nome do evento K. O parâmetro de carga útil passa a ser Events[K], portanto o nome e a carga útil precisam corresponder.

interface Events { login: { userId: string }; logout: void }
function emit<K extends keyof Events>(event: K, payload: Events[K]) {
  console.log("emit", event, JSON.stringify(payload));
}
emit("login", { userId: "u1" });

A carga útil incorreta é um erro de compilação

Se a carga útil não corresponder ao nome do evento, TypeScript a rejeitará. O genérico associa os dois parâmetros.

interface Events { login: { userId: string } }
function emit<K extends keyof Events>(event: K, payload: Events[K]) {}
// emit("login", { id: "u1" }); // Error: id is not userId
emit("login", { userId: "u1" });
console.log("ok");

Nomes de eventos desconhecidos são rejeitados

Como K extends keyof Events, você não pode emitir um evento que não esteja no mapa.

interface Events { login: { userId: string } }
function emit<K extends keyof Events>(event: K, payload: Events[K]) {}
// emit("signup", { userId: "x" }); // Error: "signup" not a key
emit("login", { userId: "x" });
console.log("only known events");

Manipuladores tipados com on

O método on registra um manipulador cujo argumento é exatamente Events[K], para que os manipuladores recebam cargas úteis tipadas corretamente.

interface Events { login: { userId: string }; logout: void }
function on<K extends keyof Events>(event: K, handler: (payload: Events[K]) => void) {
  console.log("subscribed to", event);
}
on("login", (p) => console.log(p.userId));

O argumento do manipulador é inferido

Você não anota o parâmetro do manipulador; TypeScript o infere a partir do nome do evento, oferecendo preenchimento automático completo dentro do corpo do manipulador.

interface Events { message: { text: string } }
function on<K extends keyof Events>(event: K, handler: (p: Events[K]) => void) {}
on("message", (p) => {
  // p is { text: string }
  console.log(p.text.toUpperCase());
});

Tratando eventos sem carga útil

Para eventos void, o manipulador simplesmente não recebe nenhum argumento útil. Você pode chamar o manipulador sem dados.

interface Events { logout: void }
function on<K extends keyof Events>(event: K, handler: (p: Events[K]) => void) {}
on("logout", () => console.log("logged out"));

Combinando emit e on

Juntos, emit e on formam um sistema de publicação/assinatura tipado. Emitir um evento entrega uma carga útil corretamente tipada aos seus manipuladores.

interface Events { ping: { at: number } }
type Handler<K extends keyof Events> = (p: Events[K]) => void;
const handlers: { ping: Handler<"ping">[] } = { ping: [] };
function on<K extends keyof Events>(e: K, h: Handler<K>) { handlers[e].push(h as Handler<"ping">); }
function emit<K extends keyof Events>(e: K, p: Events[K]) { handlers[e].forEach(h => h(p as Events["ping"])); }
on("ping", p => console.log("at", p.at));
emit("ping", { at: 5 });

Restringindo a posição da carga útil

O genérico garante que o argumento de carga útil seja verificado em relação ao evento escolhido, detectando incompatibilidades no local da chamada, e não no interior de um manipulador.

interface Events { add: { x: number; y: number } }
function emit<K extends keyof Events>(e: K, p: Events[K]) {
  return e;
}
emit("add", { x: 1, y: 2 });
// emit("add", { x: 1 }); // Error: y missing
console.log("payload checked");

Preenchimento automático para nomes de eventos

Como o primeiro parâmetro é keyof Events, os editores sugerem automaticamente nomes de eventos válidos enquanto você digita a chamada.

interface Events { open: void; close: void }
function emit<K extends keyof Events>(e: K, p: Events[K]) {}
// Typing emit(" suggests "open" and "close"
emit("open", undefined as void);
console.log("autocompleted names");

Por que os genéricos são essenciais aqui

Sem um genérico, você precisaria de sobrecargas para cada evento. Uma única assinatura genérica se adapta automaticamente a qualquer quantidade de eventos.

interface Events { a: { x: number }; b: { y: string } }
function emit<K extends keyof Events>(e: K, p: Events[K]) { return p; }
console.log(emit("a", { x: 1 }), emit("b", { y: "hi" }));

Um padrão reutilizável

O padrão emit<K>(event, payload) e on<K>(event, handler) é o núcleo de todo emissor com segurança de tipos, que encapsularemos em uma classe a seguir.

interface Events { tick: { n: number } }
function emit<K extends keyof Events>(e: K, p: Events[K]) { return e; }
function on<K extends keyof Events>(e: K, h: (p: Events[K]) => void) { return e; }
console.log(emit("tick", { n: 1 }), on("tick", p => p.n));

Verificação rápida: emit e on tipados

Teste sua compreensão sobre emit e on com segurança de tipos.

Recapitulação: emit e on com segurança de tipos

Você criou assinaturas genéricas de emit e on em que a carga útil é Events[K], portanto os nomes de eventos têm preenchimento automático, cargas úteis incorretas geram erros de compilação e os argumentos dos manipuladores são inferidos.

interface Events { login: { userId: string } }
function emit<K extends keyof Events>(e: K, p: Events[K]) { return e; }
console.log(emit("login", { userId: "u1" }));
Grátis para começar

Aprenda TypeScript com um tutor de IA — grátis

Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.

Cursos
101
Aulas
352

Perguntas Frequentes

A aula “emit e on com Segurança de Tipos” é grátis?

Sim — o texto completo de “emit e on com Segurança de Tipos” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de TypeScript Academy, atualize para CoddyKit PRO. O curso de TypeScript Academy inclui 4 aulas no total.

O que vou aprender em “emit e on com Segurança de Tipos”?

Garanta os dados associados corretos ao emitir eventos e escutá-los. Você pratica TypeScript Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar TypeScript Academy?

Nenhuma experiência prévia é necessária. TypeScript Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.

Quanto tempo leva a aula “emit e on com Segurança de Tipos”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de TypeScript Academy?

Sim. Cada aula de TypeScript Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Definindo Tipos de Mapas de Eventos
  2. emit e on com Segurança de Tipos
  3. Classe Genérica de Emissão de Eventos
  4. Inferindo Argumentos de Ouvintes
← Voltar para TypeScript Academy