Como os validadores funcionam
Todo validador é um decorator de propriedade que anexa uma regra de validação à metadata do campo. Quando o schema roda no boot, as regras são executadas na ordem em que foram declaradas na propriedade. Cada regra pode incluir uma etapa de transform, que converte a string bruta para o tipo de destino, e uma etapa de validate, que verifica se o valor convertido é aceitável. Se qualquer regra retornar uma mensagem de erro, o campo falha na validação.
Você pode empilhar múltiplos validadores em uma mesma propriedade. Um campo como uma URI do Redis, por exemplo, pode usar IsRedisUri para checar o formato e Secret para mascaramento. O pipeline executa cada regra em sequência, então Transform faz a conversão antes de Validate receber o valor. Entender essa ordem importa quando você combina transformações personalizadas com validadores de tipo embutidos.
Os validadores se organizam em seis famílias: string, número, boolean, rede, Discord e dados. Um sétimo grupo, o de validadores comuns, reúne decorators utilitários que modificam o comportamento do campo sem checar tipos.
Como escolher bem os validadores
Comece com o validador que corresponde ao tipo em runtime que você quer dentro da aplicação, e só depois adicione validadores de restrição para impor regras de negócio mais específicas. Em outras palavras, primeiro decida se o campo deve virar string, number ou boolean, e só então acrescente verificações como comprimento mínimo, correspondência por padrão ou limites numéricos.
Essa ordem deixa o schema mais fácil de ler. Qualquer pessoa que abrir o arquivo de env consegue entender rapidamente no que aquele campo se transforma no código e quais regras extras ele precisa obedecer.
Validadores de string
IsString confirma que o valor é uma string não vazia. Use-o para qualquer campo de texto livre. Há três validadores de restrição que podem ser empilhados por cima para limitar ainda mais o valor.
| Decorator | Argumentos | Descrição |
|---|---|---|
| IsString() | Nenhum | Valida que o valor é uma string não vazia. |
| MinLength(min) | min: number | Valida que a string tem pelo menos a quantidade informada de caracteres. |
| MaxLength(max) | max: number | Valida que a string tem no máximo a quantidade informada de caracteres. |
| Matches(pattern, message?) | pattern: RegExp, message?: string | Valida que a string corresponde à expressão regular informada. Aceita uma mensagem de erro personalizada opcional. |
@Env('APP_NAME')
@IsString()
@MinLength(3)
@MaxLength(64)
APP_NAME!: string;
@Env('SLUG', { secret: false })
@IsString()
@Matches(/^[a-z0-9-]+$/, 'Must be lowercase alphanumeric with hyphens')
SLUG!: string;Validadores de número
Três validadores cuidam de valores numéricos. Cada um transforma a string bruta em um number do JavaScript antes de validar o formato. Eles diferem no que aceitam depois da conversão.
| Decorator | Aceita | Valores de exemplo |
|---|---|---|
| IsNumber | Qualquer número finito, inclusive decimais | "3.14", "42", "-1.5" |
| IsInteger | Apenas números inteiros | "42", "-7", "0" |
| IsPort | Inteiro entre 1 e 65535 | "3000", "8080", "443" |
Os três convertem a string com Number() antes de validar. IsNumber rejeita NaN e strings vazias. IsInteger ainda exige que Number.isInteger() retorne verdadeiro. IsPort acrescenta uma checagem de intervalo entre 1 e 65535 por cima da exigência de inteiro.
Quatro validadores de restrição podem ser aplicados sobre qualquer campo numérico e devem vir depois do validador de tipo:
| Decorator | Argumentos | Descrição |
|---|---|---|
| Min(min) | min: number | Valida que o valor numérico é maior ou igual ao mínimo informado. |
| Max(max) | max: number | Valida que o valor numérico é menor ou igual ao máximo informado. |
| IsPositive() | Nenhum | Valida que o valor numérico é maior que zero. |
| IsNegative() | Nenhum | Valida que o valor numérico é menor que zero. |
@Env('RATE_LIMIT')
@IsNumber()
@Min(1)
@Max(1000)
RATE_LIMIT!: number;
@Env('MAX_RETRIES')
@IsInteger()
@IsPositive()
MAX_RETRIES!: number;
@Env('HTTP_PORT', { secret: false })
@IsPort()
HTTP_PORT!: number;Validador boolean
O validador IsBoolean transforma representações em string em booleans nativos. Ele aceita quatro valores brutos: "true", "false", "1" e "0". A comparação ignora maiúsculas e minúsculas e remove espaços em volta, então " TRUE " vira true. Qualquer outro valor falha na validação.
Depois da transformação, a propriedade passa a conter um boolean real do JavaScript. Você nunca precisa comparar com a string "true" no código. Essa é a forma recomendada de tratar feature flags e toggles armazenados em variáveis de ambiente.
@Env('ENABLE_METRICS', { default: 'false', secret: false })
@IsBoolean()
ENABLE_METRICS!: boolean;Validadores de rede
Cinco validadores cobrem formatos comuns relacionados a rede. Cada um checa a string contra um padrão específico sem transformar o valor, porque URIs e endereços de rede continuam sendo strings.
| Decorator | Valida | Exemplo |
|---|---|---|
| IsUrl(options?) | Qualquer URL interpretável pelo construtor URL. Passe a opção https para rejeitar URLs que não usem HTTPS. | "https://api.example.com" |
| IsEmail | Formato básico de email, como [email protected] | "[email protected]" |
| IsHost | Hostname, endereço IPv4 ou endereço IPv6 | "localhost", "192.168.1.1" |
| IsMongoUri | URI que começa com mongodb:// ou mongodb+srv:// | "mongodb+srv://user:[email protected]/db" |
| IsRedisUri | URI que começa com redis:// ou rediss:// | "redis://localhost:6379" |
Validadores de rede funcionam muito bem com Secret para mascarar credenciais no log de inicialização. Uma string de conexão do MongoDB contém senha, então o comportamento padrão de mascaramento já a protege automaticamente. Hostnames e portas são seguros para exibir, então marque esses campos com secret: false nas opções de @Env.
@Env('CALLBACK_URL', { secret: false })
@IsUrl({ https: true })
CALLBACK_URL!: string;
@Env('MONGO_URI')
@IsMongoUri()
MONGO_URI!: string;
@Env('REDIS_URI')
@IsRedisUri()
REDIS_URI!: string;
@Env('API_HOST', { default: 'localhost', secret: false })
@IsHost()
API_HOST!: string;Validadores do Discord
Quatro validadores são voltados para formatos específicos do Discord. Eles são rígidos quanto ao formato porque tokens, IDs ou webhook URLs inválidos causam falhas de autenticação difíceis de depurar no momento da conexão.
| Decorator | Valida |
|---|---|
| IsDiscordToken() | String base64url com três segmentos e 59 a 100 caracteres. Valida se cada segmento usa apenas caracteres base64url. |
| IsDiscordId() | Snowflake numérico com 17 a 19 dígitos. Rejeita caracteres que não são dígitos e comprimentos fora do intervalo. |
| IsDiscordWebhookUrl() | Webhook URL completa do Discord correspondente ao caminho de webhook em discord.com, canary.discord.com ou ptb.discord.com. Sempre marque esse campo com @Secret() porque a URL embute um token. |
| IsDiscordClientSecret() | OAuth2 client secret: string não vazia, segura para URL, com 24 a 64 caracteres e sem espaços em branco. Sempre marque esse campo com @Secret(). |
Para valores específicos do Discord, a validação rígida compensa o esforço extra. Uma webhook URL malformada ou um client secret incorreto costuma falhar longe do arquivo de env, então a validação no boot é um dos pontos mais baratos para detectar esse tipo de erro.
@Env('DISCORD_TOKEN')
@IsDiscordToken()
TOKEN!: string;
@Env('GUILD_ID', { secret: false })
@IsDiscordId()
GUILD_ID!: string;
@Env('ALERT_WEBHOOK')
@IsDiscordWebhookUrl()
@Secret()
ALERT_WEBHOOK!: string;
@Env('DISCORD_CLIENT_SECRET')
@IsDiscordClientSecret()
@Secret()
CLIENT_SECRET!: string;Validadores de dados
Dois validadores lidam com dados estruturados armazenados como strings em variáveis de ambiente.
IsJson interpreta o valor bruto com JSON.parse durante a fase de transformação. Se o parsing der certo, a propriedade passa a conter o objeto ou array JavaScript resultante. Se falhar, a string bruta segue adiante e a fase de validação a rejeita. Isso é útil para configurações complexas que você quer armazenar como uma string JSON em uma única variável de ambiente.
IsEnum aceita um array de valores permitidos e verifica se o valor resolvido corresponde a um deles. Ele não transforma o valor, então funciona com strings por padrão. Você pode combiná-lo com um validador de tipo como IsNumber quando os valores do enum forem numéricos, já que IsEnum faz a checagem depois que todas as transformações terminam.
@Env('FEATURE_FLAGS')
@IsJson()
FEATURE_FLAGS!: Record<string, boolean>;
@Env('LOG_LEVEL', { default: 'info', secret: false })
@IsEnum(['debug', 'info', 'warn', 'error'])
LOG_LEVEL!: string;Validadores comuns
Os validadores comuns não checam tipos. Em vez disso, eles alteram como o campo se comporta dentro do pipeline. Você os usa junto com validadores de tipo para controlar opcionalidade, mascaramento, valores padrão e lógica personalizada.
IsOptional e Default tornam o campo opcional, mas Default também fornece um fallback concreto. Se você usar Default, o campo sempre resolve para algum valor. Se usar apenas IsOptional, a propriedade pode ser undefined em runtime.
Transform intercepta a string bruta e retorna o novo valor. Ele roda antes de qualquer etapa de validate da mesma regra e antes das regras declaradas abaixo dela. Isso permite normalizar dados, como remover espaços extras ou dividir listas separadas por vírgula, antes que o validador de tipo veja o valor.
Validate adiciona uma checagem personalizada ao pipeline. A função recebe o valor já transformado e retorna true quando ele é aceitável ou uma string de erro quando não é. Essa é a rota de escape para regras de negócio que os validadores embutidos não cobrem.
@Env('ALLOWED_ORIGINS', { secret: false })
@Transform((raw) => raw.split(',').map((s) => s.trim()))
@Validate((value) => Array.isArray(value) && value.length > 0 ? true : 'Expected at least one origin')
ALLOWED_ORIGINS!: string[];