0

Lidar com `unknown` no TypeScript... não é uma dor de cabeça?

Olá! 👋

Sou engenheiro frontend e moro nos Países Baixos. Neste momento, também estou sofrendo com a temporada de alergias 😿

Respostas de APIs, dados de formulários, informações vindas de serviços externos...

No TypeScript, frequentemente precisamos trabalhar com valores do tipo unknown, e tratá-los corretamente pode acabar se tornando uma verdadeira dor de cabeça no dia a dia.

Unknown e sua força gravitacional

Sim, o unknown parece ter uma força gravitacional quase cósmica.

Mesmo assim, queremos tratar os tipos com segurança, certo?

Foi pensando nisso que criei o is-kit, uma biblioteca para criar e combinar type guards.

is-kit

O que é o is-kit?

O is-kit é um toolkit leve e sem dependências para criar type guards reutilizáveis em TypeScript.

Ele ajuda você a escrever pequenas funções no estilo isFoo, combiná-las em verificações mais completas de runtime e manter o type narrowing natural dentro do fluxo normal da aplicação.

A proposta é oferecer verificações seguras, combináveis e fáceis de usar, sem obrigar você a adotar um fluxo pesado baseado em schemas.

Com o is-kit, você pode:

  • Criar e reutilizar type guards tipados
  • Combinar guards com and, or, not e oneOf
  • Validar estruturas de objetos e coleções
  • Interpretar ou verificar valores unknown sem um grande framework de schemas

📚 Documentação do is-kit

O is-kit é especialmente útil para narrowing dentro da aplicação, filtragem de dados e criação de guards reutilizáveis.

🤔 Por que usar o is-kit?

Você já se cansou de escrever as mesmas verificações isFoo repetidamente?

O is-kit pode ser uma boa escolha quando você quer:

  • Criar funções isX reutilizáveis em vez de verificações isoladas
  • Manter a validação em runtime leve e sem dependências
  • Refinar tipos diretamente em if, filter e outros fluxos normais do TypeScript
  • Combinar pequenas regras de validação

Bibliotecas como o Zod seguem uma abordagem centrada em schemas.

O is-kit, por outro lado, concentra-se no refinamento dos tipos dentro do código que você já possui.

Em vez de pensar que está “escrevendo uma validação”, você pode enxergar o is-kit como uma forma de adicionar segurança de tipos aos seus if cotidianos.

Se o Zod é especialmente útil nas fronteiras da aplicação, como APIs e inputs, o is-kit é voltado para a lógica interna da aplicação.


Um exemplo simples

Imagine que você precise verificar várias vezes se um valor é uma string com no máximo três caracteres.

Com o is-kit, você pode definir essa regra uma única vez e reutilizá-la:

import { define, isString } from "is-kit";

const isShortString = define<string>(
  (value) => isString(value) && value.length <= 3,
);

Depois, basta utilizá-la normalmente:

import { isShortString } from "~/utils/is";

declare const input: unknown;

// Antes: repetimos as condições toda vez
if (typeof input === "string" && input.length <= 3) {
  input.toUpperCase();
}

// Depois: reutilizamos o guard
if (isShortString(input)) {
  input.toUpperCase();
}

Esse estilo funciona naturalmente com if, filter, map e outras estruturas que já fazem parte da lógica da aplicação.


🐾 Como o is-kit evoluiu

Já se passaram aproximadamente seis meses desde o lançamento da versão v1.0.

Naquela época, o is-kit começou como uma pequena biblioteca de type guards, com recursos básicos como:

  • define
  • and
  • or
  • struct
  • arrayOf

Desde então, até a versão v1.6, ele evoluiu gradualmente para algo mais prático:

👉 Um toolkit para lidar com valores unknown em aplicações reais.

Vamos conhecer cinco melhorias importantes.


🪄 1. Diferenciando uma propriedade ausente de uma propriedade com valor undefined

Uma situação comum em respostas de APIs:

  • Uma propriedade não existe no objeto
  • A propriedade existe, mas seu valor é undefined

Esses dois casos não são iguais.

Na versão v1.5.0, foi adicionado o optionalKey(...):

import { isString, optional, optionalKey, struct } from "is-kit";

const isUser = struct({
  id: isString,
  nickname: optionalKey(isString),
  displayName: optionalKey(optional(isString)),
});

Isso permite representar explicitamente os dois casos.

No exemplo:

  • nickname pode não existir, mas, quando existe, precisa ser uma string
  • displayName pode não existir e também pode existir com o valor undefined

🔑 2. Narrowing baseado em propriedades com hasKey, hasKeys e narrowKeyTo

Entre as versões v1.1.13 e v1.4.0, foram adicionadas funções para trabalhar com propriedades específicas:

import {
  hasKeys,
  narrowKeyTo,
  oneOfValues,
  struct,
  isString,
  isNumber,
} from "is-kit";

const isUser = struct({
  id: isString,
  age: isNumber,
  role: oneOfValues("admin", "guest", "trial"),
});

const hasRoleAndId = hasKeys("role", "id");
const byRole = narrowKeyTo(isUser, "role");
const isGuest = byRole("guest");

Isso permite criar novos guards a partir de verificações existentes, sem precisar redefinir toda a estrutura.


🧪 3. assert para validações fail-fast

O assert foi adicionado na versão v1.2.0:

import { assert, isString } from "is-kit";

declare const input: unknown;

assert(isString, input, "input must be a string");

input.toUpperCase();

Depois que o assert é executado com sucesso, o TypeScript entende que input é uma string.

Assim, também podemos usar os guards em um fluxo fail-fast quando necessário.


✨ 4. Suporte a Set e Map

Na versão v1.6.0, o is-kit recebeu suporte a estruturas como Set e Map:

import { mapOf, setOf, isString, isNumber } from "is-kit";

const isTags = setOf(isString);
const isScores = mapOf(isString, isNumber);

Nem todos os dados de uma aplicação real são arrays.

Esse suporte amplia as verificações para estruturas comuns do JavaScript.


🥏 5. Tratamento de casos especiais envolvendo números

Desde as versões v1.1.x, foram adicionados vários guards numéricos:

  • isInteger
  • isSafeInteger
  • isPositive
  • isNegative
  • isNaN
  • isInfiniteNumber
  • isZero

Eles ajudam a expressar com mais precisão o que significa um número válido em cada contexto.

Em muitos casos, verificar apenas typeof value === "number" não é suficiente.


🌟 Mais recursos

Existem várias outras funções disponíveis no is-kit.

Você pode conhecer todas elas na documentação:

📚 is-kit-docs.vercel.app


🎯 Resumo

O is-kit começou como uma pequena biblioteca de type guards combináveis.

Com o tempo, ele evoluiu para:

👉 Um toolkit prático para lidar com valores unknown dentro da lógica de aplicações TypeScript.

Entre as principais melhorias estão:

  • Estruturas de objetos mais expressivas com optionalKey
  • Narrowing baseado em propriedades
  • Assertions no estilo fail-fast
  • Suporte a coleções como Set e Map
  • Guards mais precisos para valores numéricos

O objetivo do is-kit é simples:

Fazer com que código type-safe também seja natural de escrever.

Caso você experimente o projeto e tenha alguma ideia ou feedback, fique à vontade para compartilhar!

Até o próximo artigo 👋

Conheça o is-kit no GitHub


Artigo original em inglês:

https://dev.to/nyaomaru/handling-unknown-in-typescript-isnt-it-painful-4dec

Carregando publicação patrocinada...