ArkType, uma alternativa mais rápida ao Zod
Compare a sintaxe do ArkType e do Zod, a inferência de tipos, a velocidade de validação e o tratamento de respostas de API. Saiba quando usar ArkType ou manter Zod.
O ArkType é um validador de runtime para TypeScript que escreve schemas como strings semelhantes a TypeScript e os compila em validadores otimizados. Para uma equipe com uma base de código estável em Zod, raramente vale a pena fazer uma migração completa. Para um projeto novo ou para um caminho crítico de validação, vale a pena experimentar.
Se você usa Zod, provavelmente já viu o gráfico de benchmark do ArkType e se perguntou se a velocidade compensa aprender uma nova sintaxe.
Este artigo migra um único schema User do Zod para o ArkType. Ele aborda inferência, desempenho, validação de uma resposta de API e os trade-offs, e depois diz claramente quando continuar no Zod. Os exemplos usam o ArkType 2.2 e o Zod 4.
Principais conclusões
- O ArkType define schemas como strings semelhantes a TypeScript, então
"'android' | 'ios'"se lê exatamente como o tipo union que ele produz, enquanto o Zod escrevez.enum(["android", "ios"]). - Chamar um tipo do ArkType sobre dados desconhecidos retorna o valor validado ou uma instância de
ArkErrors, então a verificação idiomática éout instanceof type.errors. - A página inicial do ArkType afirma que ele é 20x mais rápido que o Zod 4 em runtime. Esse número é do próprio fornecedor, e o Zod 4.5 já adicionou o
z.compile()para caminhos críticos. - O ArkType 2.2 aceita qualquer validador Standard Schema dentro de
type(), então um schema existente do Zod 4 pode ser aninhado em uma definição do ArkType em vez de ser reescrito antes.
Qual é a diferença entre ArkType e Zod em uma linha?
O Zod constrói um schema a partir de chamadas de métodos encadeadas, enquanto o ArkType escreve um schema como strings semelhantes a TypeScript, de modo que ele se lê como o tipo que produz. Um campo declarado como "(number | string)[]" é a anotação TypeScript que você escreveria de qualquer forma, só que entre aspas. O guia “Your First Type” do ArkType destaca que o seu editor verifica essas definições em string enquanto você digita, com autocomplete, usando o próprio sistema de tipos do TypeScript.
O mesmo schema User no Zod e no ArkType
Abaixo está o mesmo schema de três campos nas duas bibliotecas: uma string obrigatória, uma union de dois valores e um array opcional de números ou strings.
Zod 4:
import * as z from "zod"
const User = z.object({
name: z.string(),
platform: z.enum(["android", "ios"]),
versions: z.array(z.union([z.number(), z.string()])).optional(),
})
ArkType 2.2:
import { type } from "arktype"
const User = type({
name: "string",
platform: "'android' | 'ios'",
"versions?": "(number | string)[]",
})
A versão em ArkType não tem chamadas de builder aninhadas. A opcionalidade também muda de lugar: o ArkType marca a chave com ?, como faz o TypeScript, enquanto o Zod chama .optional() no valor. O ArkType também oferece uma configuração global exactOptionalPropertyTypes (adicionada na versão 2.1.12) que corresponde à opção do compilador TypeScript de mesmo nome.
| Critério | Zod 4 | ArkType 2.2 |
|---|---|---|
| Sintaxe do schema | Métodos de builder encadeados | Strings semelhantes a TypeScript e object literals |
| Campo opcional | .optional() no valor | "key?" na chave |
| Tipo estático | z.infer<typeof User> | typeof User.infer |
| Validar dados desconhecidos | User.safeParse(data) | User(data) |
| Verificação de falha | !result.success | out instanceof type.errors |
| Texto de erro legível | Construído a partir de result.error.issues | out.summary |
| Compilação | Opcional via z.compile() (Zod 4.5+) | Embutida na forma como as definições são processadas |
Inferência de tipos: typeof User.infer vs z.infer
As duas bibliotecas derivam o tipo estático a partir do schema de runtime, então você nunca escreve a interface manualmente. Só a sintaxe de extração é diferente.
// Zod
type User = z.infer<typeof User>
// ArkType
type User = typeof User.infer
No Zod, z.infer é um utilitário genérico que você aplica ao tipo do schema. No ArkType, infer é uma propriedade do próprio tipo, lida por meio de typeof. Com o schema acima, ambos geram o mesmo formato: { name: string; platform: "android" | "ios"; versions?: (number | string)[] }.
O ArkType é mais rápido que o Zod?
O ArkType constrói um validador otimizado antecipadamente, no momento em que cada Type é criado. A documentação de configuração do ArkType descreve essa etapa de pré-compilação e uma opção jitless que a desativa. A página inicial do ArkType afirma que o ArkType é 20x mais rápido que o Zod 4 em runtime. Essa é uma alegação de benchmark do próprio fornecedor, não uma medição independente.
Desde então, o Zod 4.5 reduziu parte dessa diferença com o z.compile(). Como explica a documentação de compilação do Zod, o z.compile() percorre um schema uma única vez e gera uma função de verificação linear, que o Zod executa com new Function(). Se a entrada falhar nessa verificação rápida, o Zod a repassa para o parser normal, de modo que os erros detalhados continuam os mesmos. O README do Zod relata um ganho mediano de 2,4x em um benchmark com 55 schemas. Portanto, uma comparação com o Zod 4 não compilado não diz como o ArkType se sai em relação a um schema Zod compilado.
Para validação de formulários, a diferença de velocidade entre ArkType e Zod raramente importa. Algumas validações por interação do usuário não serão o seu gargalo. A velocidade passa a ser um fator quando um schema é executado milhares de vezes por segundo, por exemplo em request handlers ou importações em lote.
Validando uma resposta de API de ponta a ponta
A tarefa real mais comum é verificar uma resposta de fetch antes que o restante da aplicação confie nela. Aqui está a mesma função nas duas bibliotecas.
ArkType:
async function getUser(id: string) {
const res = await fetch(`/api/users/${id}`)
const out = User(await res.json())
if (out instanceof type.errors) {
console.error(out.summary)
return null
}
return out // typed as User
}
Zod:
async function getUser(id: string) {
const res = await fetch(`/api/users/${id}`)
const result = User.safeParse(await res.json())
if (!result.success) {
console.error(result.error.issues)
return null
}
return result.data
}
Zod e ArkType retornam formatos diferentes na validação. O safeParse do Zod retorna um objeto de resultado discriminado com success, data e error. Um tipo do ArkType retorna diretamente o valor validado ou uma instância de ArkErrors. Após a verificação com instanceof, o TypeScript estreita out para User. out.summary é uma única mensagem legível que lista cada caminho com falha, o que era esperado ali e o que foi recebido.
ArkErrors também pode ser passado diretamente para JSON.stringify(), uma mudança que chegou no ArkType 2.1.10 e está listada nas notas de lançamento da versão 2.2. Isso significa que uma falha de validação pode ir direto para uma resposta de erro da API ou para uma entrada de log sem que seja preciso escrever um formatador antes.
O trade-off: ecossistema e familiaridade vs uma nova gramática
A principal vantagem do Zod sobre o ArkType é tudo o que existe ao redor dele. Ele tem um amplo ecossistema de integrações, e a maioria dos desenvolvedores TypeScript já sabe ler um schema Zod. Parte dessa diferença está diminuindo graças ao Standard Schema, uma interface compartilhada que Zod, ArkType e Valibot implementam. Antes de migrar, verifique se a sua biblioteca de formulários, o seu router e a sua camada de RPC aceitam Standard Schema.
Os custos do ArkType são reais:
- Uma nova gramática. Unions, arrays e chaves opcionais parecem familiares, mas restrições e expressões mais avançadas formam uma linguagem em string que sua equipe precisa aprender.
- Os erros aparecem como erros de tipo em strings. Um erro de digitação como
"strng"é detectado pelo TypeScript no editor, mas como um erro em uma definição em string, e não como um método inexistente, então sua equipe precisa se acostumar a ler um novo tipo de mensagem de erro.
O ArkType 2.2 torna possível uma adoção parcial. A documentação de integrações do ArkType mostra que type() aceita qualquer validador Standard Schema, sozinho ou dentro de uma definição de objeto, e o infere e verifica como uma definição nativa do ArkType. Isso significa que os schemas existentes do Zod 4 podem permanecer como estão:
import * as z from "zod"
import { type } from "arktype"
const ZodDevice = z.object({ platform: z.enum(["android", "ios"]) })
const User = type({
name: "string",
device: ZodDevice, // Standard Schema validator nested in ArkType (2.1.28+)
})
Se a sua principal restrição for o tamanho do bundle, e não a velocidade, o Valibot é a biblioteca a se considerar.
Quando você deve migrar do Zod para o ArkType?
A maioria das equipes com uma base de código Zod estável e integrações funcionando não deve migrar para o ArkType ainda. O custo da migração é maior do que um ganho de velocidade que o compilador do Zod 4.5 já cobre parcialmente. Experimente o ArkType quando:
- Você estiver começando um projeto novo e suas ferramentas aceitarem Standard Schema.
- Você tiver um caminho crítico comprovado, como um endpoint de alto throughput ou um job em lote, em que o profiling mostre o custo da validação.
- Você quiser testá-lo em um único endpoint, aninhando schemas Zod existentes dentro de definições do ArkType em vez de reescrevê-los.
Caso contrário, continue validando dados com Zod e experimente o z.compile() nos schemas executados com mais frequência.
Conclusão
A principal vantagem do ArkType é a legibilidade: o schema se parece com o tipo que produz, e ele oferece um validador rápido e compilado. A vantagem do Zod é que ele já está integrado à sua stack. Para testar a diferença com baixo custo, escolha um endpoint com validação intensa, defina-o com o ArkType 2.2 aninhando seus schemas Zod existentes e faça o profiling comparando com uma versão z.compile() do mesmo schema Zod antes de mudar qualquer outra coisa.
Perguntas frequentes
O ArkType funciona no Cloudflare Workers ou sob uma Content Security Policy restritiva?
Sim. O ArkType pré-compila a lógica de validação com new Function quando um Type é instanciado e desativa isso automaticamente em ambientes que não suportam new Function, como o Cloudflare Workers. Sob uma CSP sem 'unsafe-eval', defina a opção jitless como true. Configure-a a partir de 'arktype/config' antes de importar qualquer coisa de 'arktype', para que as keywords nativas a reconheçam. A validação continua funcionando, apenas sem os validadores pré-compilados.
O ArkType consegue gerar JSON Schema como o Zod 4?
Sim. Todo Type do ArkType tem um método toJsonSchema(), e o ArkType 2.2 adicionou o pacote @ark/json-schema para a direção inversa, que converte JSON Schema em Types do ArkType. Recursos sem equivalente em JSON Schema, como morphs, chaves symbol ou Date, fazem o toJsonSchema() lançar um erro por padrão, e uma opção fallback permite tratar cada caso. O Zod 4 atende à mesma necessidade com z.toJSONSchema().
Qual é o equivalente no ArkType ao transform() do Zod?
O ArkType chama as transformações de morphs e as anexa com .pipe(), por exemplo type('string').pipe(s => s.trim()). Keywords de parse nativas, como 'string.json.parse' e 'string.numeric.parse', lidam com conversões comuns sem precisar de callback. Se um morph lançar uma exceção, o ArkType assume que você pretendia interromper a execução. Use .pipe.try() para transformar a exceção lançada em um resultado ArkErrors. O tipo inferido reflete a saída do morph.
O ArkType pode lançar um erro com dados inválidos, como o parse() do Zod, em vez de retornar erros?
Sim. Chamar out.throw() em um resultado ArkErrors lança o erro, e a opção global onFail faz com que todo Type lance um erro com dados inválidos: configure({ onFail: errors => errors.throw() }) a partir de 'arktype/config'. Declare o mesmo onFail na interface global ArkEnv para que o TypeScript saiba que as invocações não retornam mais ArkErrors. O estilo padrão de valor de retorno corresponde ao safeParse() do Zod, e o onFail corresponde ao parse().
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.
Star on GitHub12k