af aprenda frontend
módulo 05 tipos

Funções tipadas — parâmetros e retornos.

Parâmetros, retornos, parâmetros opcionais, valores padrão, rest. void e never em retornos. Sobrecargas em alto nível.

Funções são o principal ponto onde TypeScript requer anotações explícitas — os parâmetros não são inferidos pelo compilador. Entender como tipar parâmetros, retornos e as variações (opcionais, padrão, rest) é o que permite converter as funções do blog de JavaScript para TypeScript com segurança.

Parâmetros e retorno

A anotação básica: dois-pontos após o parâmetro para o tipo, e dois-pontos após a lista de parâmetros para o retorno:

ts
// parâmetro: palavras: number — retorno: number
function calcularTempoLeitura(palavras: number): number {
  return Math.ceil(palavras / 238);
}

// parâmetro: dateString: string — retorno: string
function formatarData(dateString: string): string {
  return new Intl.DateTimeFormat("pt-BR", {
    year: "numeric",
    month: "long",
    day: "numeric",
  }).format(new Date(dateString));
}

// parâmetro: titulo: string — retorno: string
function gerarSlug(titulo: string): string {
  return titulo
    .toLowerCase()
    .trim()
    .replace(/\s+/g, "-")
    .replace(/[^a-z0-9-]/g, "");
}

// dois parâmetros — retorno: string
function truncar(texto: string, max: number = 160): string {
  if (texto.length <= max) return texto;
  return texto.slice(0, max).trimEnd() + "…";
}
utils.ts — funções do blog com parâmetros e retornos tipados.

O tipo de retorno é opcional — TypeScript infere do return. Mas em funções exportadas, anotar o retorno serve como contrato: se a implementação mudar de forma que o tipo de retorno mude, o compilador avisa antes de os chamadores quebrarem.

Parâmetros opcionais e valores padrão

Dois mecanismos para parâmetros que podem ser omitidos na chamada:

ts
// parâmetro opcional: x?: string
// dentro da função, x tem tipo string | undefined
// você precisa verificar antes de usar
function exibirNotificacao(mensagem: string, tipo?: string): void {
  const classe = tipo ?? "info"; // tipo pode ser undefined — usar ?? como fallback
  console.log(`[${classe}] ${mensagem}`);
}

exibirNotificacao("Artigo salvo");          // ok — tipo é omitido
exibirNotificacao("Erro ao salvar", "erro"); // ok — tipo é "erro"

// parâmetro com valor padrão: x: string = "padrão"
// dentro da função, x SEMPRE tem tipo string — o padrão é usado quando omitido
function truncar(texto: string, max: number = 160): string {
  // max é sempre number — não precisa de ?? aqui
  if (texto.length <= max) return texto;
  return texto.slice(0, max).trimEnd() + "…";
}

truncar("texto longo...");     // ok — max é 160
truncar("texto longo...", 80); // ok — max é 80
Opcional vs. padrão — comportamento diferente dentro da função.

A diferença: com x?: string, o tipo dentro da função é string | undefined — você precisa lidar com a possibilidade de não ter sido passado. Com x: string = "padrão", o padrão já cobre o caso de omissão e o tipo dentro da função é sempre string.

Rest parameters tipados

Rest parameters (...args) agrupam argumentos extras em um array — o tipo é sempre um array:

ts
// ...tags: string[] — aceita qualquer número de strings
function criarArtigo(titulo: string, ...tags: string[]): Artigo {
  return {
    id: Math.random(),
    titulo,
    tags,
    curtidas: 0,
    publicado: false,
    publicadoEm: null,
    descricao: "",
  };
}

criarArtigo("CSS em geral");                         // tags é []
criarArtigo("Flexbox", "css", "layout");             // tags é ["css", "layout"]
criarArtigo("Grid", "css", "layout", "avançado");    // tags é ["css", "layout", "avançado"]
Rest parameters — múltiplos argumentos do mesmo tipo.

Desestruturação tipada nos parâmetros

Quando uma função recebe um objeto com vários campos, desestruturar no parâmetro é mais limpo que acessar artigo.titulo, artigo.descricao dentro do corpo:

ts
interface Artigo {
  id: number;
  titulo: string;
  descricao: string;
  tags: string[];
  curtidas: number;
  publicado: boolean;
  publicadoEm: string | null;
}

// desestruturar diretamente no parâmetro — a interface descreve a forma
function renderizarCard({ titulo, descricao, tags, curtidas }: Artigo): string {
  return `
    <article>
      <h2>${titulo}</h2>
      <p>${truncar(descricao)}</p>
      <div>${tags.map(t => `<span>${t}</span>`).join("")}</div>
      <span>${curtidas} curtidas</span>
    </article>
  `;
}

// alternativa inline — menos reutilizável
function renderizarCard({
  titulo,
  descricao,
}: { titulo: string; descricao: string }): string {
  // ...
}
Desestruturação nos parâmetros com interface.

Quando a forma do objeto é usada em mais de um lugar, extrai para uma interface — é mais reutilizável e mantém um único ponto para alterar.

Tipos de função

Funções são valores em JavaScript. Em TypeScript, o tipo de uma função descreve seus parâmetros e retorno. Isso é necessário quando você precisa tipar uma variável que guarda uma função, ou um parâmetro que recebe uma função como callback:

ts
// type alias para um tipo de função
type Handler = (event: MouseEvent) => void;
type Transformador<T, U> = (item: T) => U;
type Predicado<T> = (item: T) => boolean;

// usar o tipo em um parâmetro
function aoClicar(elemento: HTMLElement, handler: Handler): void {
  elemento.addEventListener("click", handler);
}

// função que aceita um transformador genérico
function mapear<T, U>(array: T[], fn: Transformador<T, U>): U[] {
  return array.map(fn);
}

// na prática — tipar o handler de eventos do blog
type HandlerClick = (event: MouseEvent) => void;

function registrarToggleTema(handler: HandlerClick): void {
  const botao = document.getElementById("botao-tema");
  botao?.addEventListener("click", handler);
}
Tipos de função — tipar callbacks e handlers.

A sintaxe de tipo de função é (param: Tipo) => RetornoTipo. Para múltiplos parâmetros: (a: TipoA, b: TipoB) => RetornoTipo.

void e never

Dois tipos de retorno especiais que representam situações distintas:

void: a função não retorna um valor utilizável. Ela pode retornar undefined implicitamente (sem return, ou com return;), mas o chamador não deve depender desse valor. A maioria dos event handlers tem retorno void.

never: a função nunca retorna. Isso acontece quando a função sempre lança uma exceção ou entra em loop infinito. never é diferente de voidvoid significa “retorna undefined”; never significa “nunca chega ao fim”:

ts
// void: a função termina mas não retorna valor útil
function exibirNotificacao(mensagem: string): void {
  const el = document.getElementById("notificacao");
  if (el) el.textContent = mensagem;
  // return implícito — retorna undefined
}

// never: a função NUNCA retorna
function falharCom(mensagem: string): never {
  throw new Error(mensagem);
  // TypeScript sabe que o código depois disso é inatingível
}

// never em exhaustive check — garantir que todos os casos de um union foram tratados
type Tema = "claro" | "escuro";

function aplicarTema(tema: Tema): void {
  if (tema === "claro") {
    document.documentElement.removeAttribute("data-theme");
  } else if (tema === "escuro") {
    document.documentElement.setAttribute("data-theme", "escuro");
  } else {
    // TypeScript sabe que tema é never aqui — todos os casos foram cobertos
    // se Tema ganhar um terceiro valor, isso vira erro de compilação
    const _exaustivo: never = tema;
    throw new Error(`Tema não tratado: ${_exaustivo}`);
  }
}
void vs never — quando a função termina vs. quando não termina.

O padrão de exhaustive check com never é valioso: se você adicionar "sistema" ao tipo Tema, o compilador vai apontar o erro no else — você é forçado a tratar o novo caso.

Resumo

  • Parâmetros sempre precisam de anotação de tipo. Retornos são opcionais mas recomendados em funções exportadas como contrato.
  • Parâmetro opcional (x?: string) tem tipo string | undefined dentro da função — precisa de verificação. Valor padrão (x: string = "padrão") tem tipo string — o padrão cobre o caso de omissão.
  • Rest parameters (...args: string[]) agrupam argumentos extras em um array tipado.
  • Desestruturação nos parâmetros com uma interface é mais limpa que receber o objeto inteiro e acessar propriedades individualmente.
  • Tipos de função (type Handler = (event: MouseEvent) => void) descrevem callbacks e são usados para tipar parâmetros que recebem funções.
  • void: função que termina sem retornar valor útil. never: função que nunca termina (sempre lança erro). never em else serve para verificar exaustividade de unions.
/ checkpoint verifique seu entendimento
questão 1 de 4

Qual é a diferença entre um parâmetro opcional (x?: string) e um com valor padrão (x: string = 'padrão')?