Anúncios incomodam? Ir Sem anúncios Hoje

Tipos de Utilidade do TypeScript — Os Que Valem a Pena Memorizar (e os Demais)

Atualizado em

Parcial, Escolha, Omita, Gravação, TipoDeRetorno, Parâmetros, Aguardado — oito tipos úteis com exemplos antes e depois e uma avaliação honesta sobre quais você usará todas as semanas.

Tipos de Utilidade do TypeScript — Os Que Valem a Pena Memorizar (e os Demais) 1
ANUNCIADO Remover?

Você provavelmente já leu uma página de documentação do TypeScript que lista mais de 20 tipos úteis em ordem alfabética, definindo cada um em uma frase, e ficou em dúvida sobre quais deles é melhor internalizar e quais existem apenas para pessoas que escrevem código interno de framework. Esta é a versão mais honesta: oito tipos, exemplos concretos antes e depois, e uma resposta direta sobre o uso diário versus o uso ocasional.

Se você estiver começando a partir de JSON bruto e ainda não tiver escrito suas interfaces, o convertedor de JSON para TypeScript vai te levar a uma interface básica em segundos — então volte aqui para aplicar esses tipos úteis sobre ela.

Partial — Uso semanal. Aprenda primeiro.

Torna todas as propriedades de T opcionais. O caso canônico é atualizações no estilo PATCH, onde você envia apenas os campos que mudaram.

// Before: manually duplicating the interface with optional versions of everything
interface UserUpdate {
  name?: string;
  email?: string;
  age?: number;
}

// After: Partial derives it from the source of truth
interface User {
  name: string;
  email: string;
  age: number;
}

function updateUser(id: string, updates: Partial<User>) {
  // updates.name is string | undefined — TypeScript knows
}

O problema com a versão "antes": se você adicionar um campo a User, você precisa lembrar de adicionar também a UserUpdate . Com Partial<User>, adicionar um campo à interface de origem torna esse campo disponível nas atualizações automaticamente. Os tipos permanecem sincronizados.

Required — Uso mensal, mas economiza em uma situação específica.

O inverso de Partial — remove todas as ? de um tipo. Mais útil após validação: você recebe um objeto de configuração com tipagem fraca, valida que todos os campos estão presentes e então deseja que o TypeScript pare de sugerir que tudo pode ser indefinido.

// Before: after validating, you still fight undefined checks everywhere
interface Config {
  apiUrl?: string;
  timeout?: number;
  retries?: number;
}

function initApp(config: Config) {
  config.apiUrl?.trim(); // need optional chaining even after checking
}

// After: Required signals "this has been validated, stop warning me"
function validateAndInit(raw: Config): void {
  if (!raw.apiUrl) throw new Error("apiUrl required");
  if (!raw.timeout) throw new Error("timeout required");
  if (!raw.retries) throw new Error("retries required");

  const config = raw as Required<Config>;
  config.apiUrl.trim(); // no optional chaining needed
}

Observação honesta: Required<T> não faz validação em tempo de execução — você ainda precisa escrever as verificações. Ele apenas muda o que o TypeScript acredita no nível de tipo. Use para comunicar "isso já foi validado" no nível de tipo.

Pick — Uso semanal. Especifique o que você quer.

Cria um novo tipo contendo apenas as propriedades que você nomeia de T. Útil quando você quer um subconjunto de uma interface maior — formas de API pública, modelos de visualização, respostas serializadas.

// Before: manually maintaining a separate interface that drifts from User
interface UserPublicProfile {
  name: string;
  bio: string;
  avatarUrl: string;
}

// After: Pick stays in sync with the source
interface User {
  id: string;
  name: string;
  email: string;       // private — shouldn't go to clients
  passwordHash: string;  // definitely private
  bio: string;
  avatarUrl: string;
}

type UserPublicProfile = Pick<User, "name" | "bio" | "avatarUrl">;

Pick é a ferramenta certa quando a lista de propriedades que você deseja é mais curta do que a lista que você precisaria exclude. Quando isso acontece no sentido oposto, use Omit.

Omit — Uso semanal. Especifique o que você não quer.

Complemento de Pick — cria um tipo com todas as propriedades de T exceto as que você nomeia. Quando você tem uma interface grande e apenas alguns campos para excluir, Omit torna a intenção mais clara do que listar todos os campos que você deseja.

// Before: manually listing every field except the sensitive ones
// Easy to miss a new field added to User later
interface UserForClient {
  id: string;
  name: string;
  email: string;
  bio: string;
  avatarUrl: string;
  // passwordHash intentionally omitted — but a future dev might not know that
}

// After: Omit states the exclusion explicitly
type UserForClient = Omit<User, "passwordHash">;
// If User gains a new "address" field, UserForClient gets it automatically

Uma coisa que nem Pick nem Omit faz: mudar o tipo de propriedades individuais. Se você quiser selecionar campos e e transformar seus tipos, você está olhando para um tipo mapeado, que é uma ferramenta completamente diferente.

Record — Uso semanal. O dicionário tipado.

Cria um tipo de objeto onde todas as chaves são do tipo K e todos os valores são do tipo V. O verdadeiro ganho surge quando K é um tipo de união — o TypeScript dará erro se você estiver faltando uma chave. As assinaturas de índice genéricas aceitam objetos incompletos silenciosamente; Record com uma chave de união não faz isso.

// Before: index signature with no exhaustiveness checking
const rolePermissions: { [key: string]: string[] } = {
  admin: ["read", "write", "delete"],
  editor: ["read", "write"],
  // forgot "viewer" — TypeScript doesn't notice
};

// After: Record with a union key enforces completeness
type Role = "admin" | "editor" | "viewer";

const rolePermissions: Record<Role, string[]> = {
  admin: ["read", "write", "delete"],
  editor: ["read", "write"],
  viewer: ["read"],
  // TypeScript error if any Role is missing
  // TypeScript error if you try to add an unknown key
};

A verificação de exaustividade é o verdadeiro ganho. Importa quando as chaves representam algo significativo, como papéis, tipos de eventos, métodos HTTP ou códigos de status — qualquer coisa onde a ausência de um caso é um erro, e não apenas uma omissão.

ReturnType — Uso semanal se você consumir funções de terceiros.

Extraí o tipo de retorno de uma função. Mais útil quando você está consumindo uma função de uma biblioteca e deseja tipar uma variável que contém seu resultado — sem precisar importar o tipo de retorno separadamente (o que bibliotecas nem sempre exportam de forma limpa).

// Before: manually annotating the return type — it can drift
function getCurrentUser() {
  return { id: "u1", name: "Alice", roles: ["admin"] as const };
}

let cachedUser: { id: string; name: string; roles: readonly string[] };
// If getCurrentUser's return changes, this annotation doesn't update automatically

// After: ReturnType derives it and keeps in sync
type CurrentUser = ReturnType<typeof getCurrentUser>;
let cachedUser: CurrentUser;

// Especially useful with unexported library types:
import { useQuery } from "@tanstack/react-query";
type QueryResult = ReturnType<typeof useQuery>;
// No need to figure out what QueryObserverResult<...> looks like or import it

Parameters — Uso ocasional. Principalmente para envoltórios.

Extraí os tipos de parâmetros de uma função como uma tupla. Visão honesta: você não usará essa ferramenta semanal a menos que escreva muitas funções de envoltório ou utilidades de ordem superior. Mas quando precisar, não há alternativa limpa.

// Before: manually duplicating parameter types in the wrapper
function createEvent(
  type: string,
  payload: Record<string, unknown>,
  timestamp: number
) { /* ... */ }

// Every time createEvent changes, this wrapper needs a manual update:
function loggedCreateEvent(
  type: string,
  payload: Record<string, unknown>,
  timestamp: number
) {
  console.log("Creating event:", type);
  return createEvent(type, payload, timestamp);
}

// After: Parameters keeps the wrapper in sync automatically
function loggedCreateEvent(...args: Parameters<typeof createEvent>) {
  console.log("Creating event:", args[0]);
  return createEvent(...args);
}

O padrão de espalhamento + rest (...args: Parameters<F>) é a principal convenção. Também aparece em mocks de testes: jest.fn<ReturnType<F>, Parameters<F>>() dá a você um mock totalmente tipado sem precisar importar a assinatura da função separadamente.

Awaited — Use quando precisar desempacotar tipos de Promise sem chamá-los.

Adicionado no TypeScript 4.5 (lançado em novembro de 2021). Desempacota recursivamente Promise<T> para obter T. Antes de existir, obter o tipo resolvido de uma função assíncrona significava escrever um tipo condicional: ReturnType<F> extends Promise<infer U> ? U : never — que quebra em Promises duplamente envolvidas e é difícil de ler em diferenças.

// Before: conditional type to unwrap — breaks on nested Promises
async function fetchUser(id: string) {
  const res = await fetch(`/api/users/${id}`);
  return res.json() as { id: string; name: string; email: string };
}

type FetchedUser =
  ReturnType<typeof fetchUser> extends Promise<infer U> ? U : never;
// Works for Promise<T> but not Promise<Promise<T>>

// After: Awaited handles both cases cleanly
type FetchedUser = Awaited<ReturnType<typeof fetchUser>>;

// Awaited recursively unwraps:
type A = Awaited<Promise<string>>;            // string
type B = Awaited<Promise<Promise<string>>>;  // string
type C = Awaited<string>;                      // string (no-op on non-Promise)

A combinação Awaited<ReturnType<typeof fn>> vale a pena memorizar como uma unidade — cobre 90% de extração de tipos assíncronos no código de aplicação.

Cheatsheet

Tipo útilO que fazFrequência de usoCaso de uso principal
Partial<T>Todas as propriedades tornam-se opcionaisSemanalmenteCorpos de atualização PATCH
Required<T>Todas as propriedades opcionais tornam-se obrigatóriasPor mêsSinal de "completo" após validação
Pick<T, K>Mantém apenas as propriedades nomeadasSemanalmenteFormas de API pública, modelos de visualização
Omit<T, K>Remove as propriedades nomeadasSemanalmenteRemoção de campos sensíveis ou irrelevante
Record<K, V>Objeto com chaves do tipo K e valores do tipo VSemanalmenteDicionários tipados com verificação de exaustividade
ReturnType<F>Extraí o tipo de retorno de uma funçãoSemanal (especialmente com bibliotecas)Tipar uma variável a partir de um tipo inferido ou não exportado
Parameters<F>Extraí os tipos de parâmetros de uma função como uma tuplaOcasionalFunções de envoltório, mocks tipados
Awaited<T>Desempacota recursivamente tipos de PromiseOcasionalObter o tipo resolvido de funções assíncronas

Os que não estão nesta lista

O TypeScript também inclui Readonly<T>, NonNullable<T>, Extract<T,U>, Exclude<T,U>, InstanceType<C>, ConstructorParameters<C>e várias tipos literais de modelo. Eles são reais e ocasionalmente úteis, mas surgem em códigos de bibliotecas, utilidades genéricas e programação de nível de tipo — não em lógica típica de aplicação. Se você memorizou os oito acima, procure os demais quando realmente os precisar.

O princípio subjacente é o mesmo em todos eles: descrever uma transformação de um tipo existente em vez de duplicá-lo. Os nomes específicos dos tipos úteis são apenas vocabulário para expressar essa intenção ao TypeScript.

Quer eliminar anúncios? Fique sem anúncios hoje mesmo

Instale nossas extensões

Adicione ferramentas de IO ao seu navegador favorito para acesso instantâneo e pesquisa mais rápida

Ao Extensão do Chrome Ao Extensão de Borda Ao Extensão Firefox Ao Extensão Opera

O placar chegou!

Placar é uma forma divertida de acompanhar seus jogos, todos os dados são armazenados em seu navegador. Mais recursos serão lançados em breve!

ANUNCIADO Remover?
ANUNCIADO Remover?
ANUNCIADO Remover?

Notícias com destaques técnicos

Envolver-se

Ajude-nos a continuar fornecendo ferramentas gratuitas valiosas

Compre-me um café
ANUNCIADO Remover?