Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

Módulo Util no Node.js: Guia Prático

Atualizado em: 9 de agosto de 2026

Estação de trabalho usada no desenvolvimento de aplicações Node.js

O Node.js inclui funções auxiliares que resolvem tarefas recorrentes de desenvolvimento, depuração e compatibilidade. O módulo Util no Node.js oferece recursos como conversão de callbacks em Promises, inspeção de objetos, formatação de mensagens, parsing de argumentos, verificação de tipos e suporte a APIs depreciadas.

Muitas dessas funções são usadas internamente por bibliotecas e ferramentas. Elas ajudam a modernizar código legado, produzir logs legíveis e criar interfaces de linha de comando sem dependências externas. Entretanto, alguns recursos são destinados a uso interno ou possuem comportamento específico que precisa ser entendido.

Neste guia, você aprenderá a usar promisify(), callbackify(), inspect(), format(), parseArgs(), types, deprecate() e outras funções com exemplos e boas práticas.

Importando o módulo Util

const util = require('node:util');

Em ES Modules:

import util from 'node:util';

A documentação oficial do módulo Util lista todas as APIs e seus níveis de estabilidade. Para conceitos assíncronos, veja Event Loop no Node.js. O guia da MDN sobre Promise complementa a base da linguagem.

Convertendo callbacks com promisify()

APIs antigas do Node.js frequentemente recebem um callback no formato (error, result). promisify() cria uma versão compatível com async e await:

const { promisify } = require('node:util');
const { exec } = require('node:child_process');

const execAsync = promisify(exec);

const { stdout } = await execAsync('node --version');
console.log(stdout.trim());

A função original precisa seguir a convenção de callback de erro primeiro. APIs com outra assinatura podem produzir resultados incorretos.

Preservando o this

Ao promisificar um método, o contexto pode ser perdido:

const object = {
  value: 42,
  getValue(callback) {
    callback(null, this.value);
  }
};

const getValue = promisify(object.getValue);

A chamada sem contexto pode falhar. Use bind:

const getValue = promisify(
  object.getValue.bind(object)
);

Promisify personalizado

Uma função pode definir sua própria implementação através do símbolo util.promisify.custom:

function legacyOperation(value, callback) {
  setTimeout(() => callback(null, value * 2), 10);
}

legacyOperation[util.promisify.custom] = async value => {
  return value * 2;
};

const modernOperation = util.promisify(legacyOperation);

Isso é útil quando a API retorna vários valores ou não segue o padrão convencional.

Não promisifique APIs que já retornam Promise

Versões modernas do Node.js oferecem módulos como node:fs/promises. Prefira a API nativa baseada em Promise em vez de envolver novamente:

const fs = require('node:fs/promises');
const content = await fs.readFile('config.json', 'utf8');

Veja File System no Node.js para operações de arquivos.

Convertendo Promises com callbackify()

callbackify() faz o caminho inverso:

async function loadUser(id) {
  return repository.findById(id);
}

const loadUserCallback = util.callbackify(loadUser);

loadUserCallback('123', (error, user) => {
  if (error) {
    console.error(error);
    return;
  }

  console.log(user);
});

Esse recurso ajuda a integrar código moderno com consumidores legados. Novos módulos devem preferir Promise ou oferecer interfaces explícitas.

Inspecionando objetos com inspect()

util.inspect() produz uma representação textual adequada para depuração:

const output = util.inspect(object, {
  depth: 4,
  colors: process.stdout.isTTY,
  compact: false
});

console.log(output);

Diferentemente de JSON.stringify(), inspect suporta referências circulares, Map, Set, BigInt e vários objetos internos.

Inspect não é serialização

O resultado foi projetado para humanos e pode mudar entre versões. Não o armazene como formato de dados nem tente reconstruir objetos a partir da string.

Controlando profundidade

util.inspect(value, {
  depth: 2,
  maxArrayLength: 50,
  maxStringLength: 500
});

Limites evitam logs gigantes. Um objeto recebido do usuário pode conter arrays enormes ou estruturas profundas.

Inspect personalizado

Classes podem definir como aparecem na depuração:

const customInspect = util.inspect.custom;

class SecretValue {
  constructor(value) {
    this.value = value;
  }

  [customInspect]() {
    return 'SecretValue([REDACTED])';
  }
}

Isso ajuda a evitar exposição acidental, mas não substitui sanitização central de logs. Outras formas de serialização ainda podem revelar o valor.

Formatando mensagens

util.format() utiliza marcadores semelhantes ao printf:

const message = util.format(
  'Usuário %s realizou %d tentativas',
  username,
  attempts
);

Marcadores comuns incluem %s, %d, %i, %f, %j, %o e %O. Verifique a documentação da versão usada.

formatWithOptions()

const message = util.formatWithOptions(
  { colors: false, depth: 3 },
  'Resultado: %O',
  result
);

Essa função combina formatação com opções de inspect.

Parseando argumentos com parseArgs()

util.parseArgs() ajuda a criar CLIs pequenas:

const { values, positionals } = util.parseArgs({
  options: {
    port: { type: 'string', short: 'p' },
    verbose: { type: 'boolean', short: 'v' },
    output: { type: 'string' }
  },
  allowPositionals: true
});

Converta e valide os valores:

const port = Number(values.port || 3000);

if (!Number.isInteger(port) || port < 1 || port > 65535) {
  throw new Error('Porta inválida');
}

Opções múltiplas

Dependendo da versão, uma opção pode aceitar múltiplos valores:

const { values } = util.parseArgs({
  options: {
    include: {
      type: 'string',
      multiple: true
    }
  }
});

Verifique a versão mínima do Node.js, pois parseArgs() evoluiu ao longo das versões.

Tokens de argumentos

A opção de tokens permite observar como cada argumento foi interpretado. Isso é útil para mensagens de erro mais precisas e para CLIs avançadas, mas aumenta complexidade.

Verificação de tipos com util.types

const { types } = util;

console.log(types.isDate(new Date()));
console.log(types.isMap(new Map()));
console.log(types.isPromise(Promise.resolve()));

Essas verificações podem ser mais confiáveis que instanceof em objetos criados em outro contexto de VM.

ArrayBuffer e Typed Arrays

types.isArrayBuffer(new ArrayBuffer(8));
types.isUint8Array(new Uint8Array(8));
types.isDataView(new DataView(new ArrayBuffer(8)));

Para dados binários, veja Buffer no Node.js.

isDeepStrictEqual()

util.isDeepStrictEqual() compara estruturas profundamente:

const equal = util.isDeepStrictEqual(
  { id: 1, tags: ['a'] },
  { id: 1, tags: ['a'] }
);

Em testes, prefira as asserções do módulo node:assert/strict, que produzem mensagens melhores. Em regra de negócio, avalie se uma comparação profunda é realmente necessária.

deprecate()

Bibliotecas podem marcar uma função como depreciada:

function oldFunction(value) {
  return newFunction(value);
}

const deprecatedFunction = util.deprecate(
  oldFunction,
  'oldFunction será removida; use newFunction',
  'DEP_APP_001'
);

Quando chamada, a função emite um warning. Forneça alternativa e prazo de migração.

Warnings de depreciação

Não use depreciação como erro imediato. Consumidores precisam de tempo para atualizar. Em projetos internos, monitore warnings no CI e trate códigos conhecidos.

inherits()

util.inherits() existe para padrões antigos de herança baseados em construtores. Em código moderno, prefira classes:

class CustomError extends Error {
  constructor(message) {
    super(message);
    this.name = 'CustomError';
  }
}

TextEncoder e TextDecoder

Alguns utilitários relacionados a codificação podem estar disponíveis globalmente ou pelo módulo, dependendo da versão. Para conversões de texto em streams, considere também node:string_decoder.

MIME e APIs novas

O módulo Util recebe recursos ao longo das versões. Sempre confirme estabilidade e compatibilidade antes de depender de uma função em biblioteca pública.

Sanitização de logs

inspect() pode revelar tokens, cookies e senhas. Antes de registrar:

function sanitize(value) {
  return {
    ...value,
    password: value.password ? '[REDACTED]' : undefined,
    token: value.token ? '[REDACTED]' : undefined
  };
}

Uma lista de campos fixa não cobre todos os segredos. Defina políticas por contexto e evite logar objetos completos.

Desempenho

Inspeção profunda e comparação estrutural podem ser caras. Não execute inspect() em nível debug quando o nível está desativado:

if (logger.isDebugEnabled()) {
  logger.debug(util.inspect(data, { depth: 3 }));
}

Logs estruturados normalmente devem receber objetos sanitizados, não strings pré-formatadas.

Testando código promisificado

test('converte callback em Promise', async () => {
  const legacy = (value, callback) => {
    callback(null, value * 2);
  };

  const modern = util.promisify(legacy);
  assert.equal(await modern(4), 8);
});

Inclua casos de erro e verifique preservação de contexto.

Erros comuns

  • Promisificar função fora do padrão: resultado e erro são interpretados incorretamente.
  • Perder this: métodos falham depois da conversão.
  • Usar inspect como JSON: o formato não é estável.
  • Inspecionar objetos enormes: CPU e logs crescem.
  • Confiar em parseArgs sem validar: todos os dados ainda são entrada externa.
  • Expor segredos no inspect: dados sensíveis aparecem em logs.
  • Usar API nova sem checar versão: produção pode executar runtime antigo.

Boas práticas para produção

  • Prefira APIs nativas baseadas em Promise.
  • Use bind ao promisificar métodos.
  • Limite profundidade e tamanho de inspeção.
  • Sanitize dados antes de registrar.
  • Valide argumentos após parseArgs.
  • Use códigos estáveis em depreciações.
  • Verifique a versão mínima do Node.js.
  • Evite utilitários legados em código novo.
  • Meça custo de inspeções em alto volume.
  • Teste casos de erro e compatibilidade.

Conclusão

O módulo Util no Node.js reúne ferramentas úteis para modernizar callbacks, depurar objetos, criar CLIs e verificar tipos. Ele reduz dependências para tarefas pequenas e oferece integração consistente com o runtime.

Esses recursos precisam ser usados com limites. Promisify depende de convenções, inspect pode revelar segredos e parseArgs não substitui validação. Ao conhecer o contrato de cada função e a versão do Node.js, você aproveita o módulo sem transformar utilidades em fonte de bugs ou overhead.

Os 10 Melhores Cursos de Programação de 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita