0Pricing
TypeScript Academy · Aula

Definindo Tipos para Chaves de Tradução

Derive uma união de chaves válidas a partir de arquivos de mensagens.

Definindo Tipos para Chaves de Tradução é uma aula grátis de TypeScript Academy no CoddyKit. Esta é a aula 1 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.

Derivando chaves de tradução válidas

Em uma configuração de i18n com segurança de tipos, o conjunto de chaves de tradução válidas é derivado do seu objeto messages. Um erro de digitação como t("greetng") se torna um erro de compilação, não um problema de string ausente em tempo de execução.

Um objeto messages

Comece com um objeto simples de messages. Ele é a única fonte de verdade tanto para os valores quanto para o tipo das chaves.

const messages = {
  greeting: "Hello",
  farewell: "Goodbye",
  cart: {
    empty: "Your cart is empty",
    checkout: "Proceed to checkout",
  },
} as const;

Chaves de nível superior com keyof

Para um objeto simples, keyof typeof fornece a união das chaves.

type TopKeys = keyof typeof messages;
// "greeting" | "farewell" | "cart"

O problema dos objetos aninhados

Os catálogos de mensagens reais são aninhados. Queremos caminhos separados por pontos, como "cart.empty", e não apenas chaves de nível superior. Precisamos de um tipo recursivo que percorra o objeto.

Um tipo recursivo de caminhos

Um tipo condicional combinado com um tipo mapeado cria caminhos separados por pontos ao recursar em objetos aninhados e prefixar as chaves. O prefixo usa um tipo de literal de modelo, escrito com crases no código real como [backtick]${K}.${Paths<T[K]>}[backtick]. Nós o mostramos abaixo como JoinPath(K, child) para manter a listagem limpa.

type JoinPath<K extends string, Rest extends string> = K + "." + Rest;
// (Real TS uses a template literal type:
//   the K dot Rest pattern delimited by backticks.)

type Paths<T> = {
  [K in keyof T & string]: T[K] extends string
    ? K
    : K | (T[K] extends object
        ? JoinPath<K, Paths<T[K]>>
        : never);
}[keyof T & string];

Aplicando o tipo

Passar o tipo de messages para Paths produz todas as chaves válidas separadas por pontos.

type MsgKey = Paths<typeof messages>;
// "greeting" | "farewell" | "cart" | "cart.empty" | "cart.checkout"

Chaves apenas das folhas

Muitas vezes você quer apenas os caminhos das folhas, ou seja, as strings reais, excluindo os objetos intermediários. Ajuste a recursão para ignorar nós que não sejam strings. O prefixo K-ponto-filho usa novamente um tipo de literal de modelo, delimitado por crases no código real, mostrado aqui como JoinPath.

type LeafPaths<T> = T extends string
  ? ""
  : {
      [K in keyof T & string]: T[K] extends string
        ? K
        : JoinPath<K, LeafPaths<T[K]>>;
    }[keyof T & string];
// "greeting" | "farewell" | "cart.empty" | "cart.checkout"

Uma função t tipada

Restrinja o parâmetro da função de tradução à união de chaves derivada, para que apenas chaves válidas sejam compiladas.

declare function t(key: LeafPaths<typeof messages>): string;

t("cart.empty");   // ok
t("cart.missing"); // Error: not a valid key

Resolvendo o tipo do valor

Você pode ir além e inferir o tipo do valor em um caminho, o que é útil quando as mensagens têm entradas que não são strings. Um tipo condicional que indexa caminhos percorre os pontos. Ele divide o caminho com um padrão de literal de modelo que, no código real, é escrito com crases como o formato Head ponto Rest com infer. Denotamos essa divisão abaixo como SplitHead/SplitRest.

// Conceptually: split "cart.empty" into Head="cart", Rest="empty"
// using a template literal pattern with infer.

type ValueAt<T, P extends string> =
  P extends SplitHead<infer Head, infer Rest>
    ? Head extends keyof T ? ValueAt<T[Head], Rest> : never
    : P extends keyof T ? T[P] : never;

Por que as const é importante

Sem as const, os valores de string se ampliam para string e você perde as informações literais necessárias mais tarde, por exemplo, para extrair marcadores de posição. Sempre declare os catálogos como constantes.

Por que isso é importante

Derivar as chaves do catálogo significa que adicionar, renomear ou remover uma mensagem atualiza instantaneamente o tipo de chave permitido em todos os lugares. Não há uma enumeração central para manter nem constantes de string obsoletas.

Verificação rápida

Confirme sua compreensão da tipagem das chaves de tradução.

Recapitulação

Você derivou uma união de chaves válidas de um objeto messages usando keyof e um tipo recursivo de caminhos com literais de modelo. As variantes que contêm apenas folhas excluem objetos intermediários, um t tipado rejeita chaves inválidas, e as const preserva as informações literais necessárias à maquinaria de tipos.

Perguntas Frequentes

A aula “Definindo Tipos para Chaves de Tradução” é grátis?

Sim — o texto completo de “Definindo Tipos para Chaves de Tradução” é 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 “Definindo Tipos para Chaves de Tradução”?

Derive uma união de chaves válidas a partir de arquivos de mensagens. 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 1 de 4.

Quanto tempo leva a aula “Definindo Tipos para Chaves de Tradução”?

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 para Chaves de Tradução
  2. Segurança de Tipos na Interpolação
  3. Pluralização com Tipos
  4. Inferência de Tipos Sensível à Localidade
← Voltar para TypeScript Academy