The util module provides essential utilities for debugging, formatting, and working with callbacks. Here's how to use it.
promisify#
1const util = require('util');
2const fs = require('fs');
3
4// Convert callback-based function to Promise
5const readFile = util.promisify(fs.readFile);
6const writeFile = util.promisify(fs.writeFile);
7
8// Use with async/await
9async function processFile() {
10 const data = await readFile('input.txt', 'utf8');
11 const processed = data.toUpperCase();
12 await writeFile('output.txt', processed);
13 console.log('Done!');
14}
15
16// Custom promisify
17const sleep = util.promisify(setTimeout);
18
19async function delayedLog(message) {
20 await sleep(1000);
21 console.log(message);
22}
23
24// Multiple callback arguments
25const dns = require('dns');
26const lookup = util.promisify(dns.lookup);
27
28// Returns { address, family } instead of two args
29const result = await lookup('example.com');
30console.log(result.address, result.family);
31
32// Custom util.promisify.custom
33dns.lookup[util.promisify.custom] = (hostname) => {
34 return new Promise((resolve, reject) => {
35 dns.lookup(hostname, (err, address, family) => {
36 if (err) reject(err);
37 else resolve({ address, family });
38 });
39 });
40};callbackify#
1const util = require('util');
2
3// Convert Promise function to callback
4async function fetchData(id) {
5 const response = await fetch(`/api/data/${id}`);
6 return response.json();
7}
8
9const fetchDataCb = util.callbackify(fetchData);
10
11// Use with callback
12fetchDataCb('123', (err, data) => {
13 if (err) {
14 console.error(err);
15 return;
16 }
17 console.log(data);
18});
19
20// Useful for legacy APIs
21async function modernFunction(options) {
22 return { success: true, data: options };
23}
24
25// Expose as callback for compatibility
26module.exports = util.callbackify(modernFunction);format and formatWithOptions#
1const util = require('util');
2
3// Printf-style formatting
4console.log(util.format('Hello, %s!', 'World'));
5// 'Hello, World!'
6
7console.log(util.format('Count: %d', 42));
8// 'Count: 42'
9
10console.log(util.format('Data: %j', { a: 1, b: 2 }));
11// 'Data: {"a":1,"b":2}'
12
13console.log(util.format('Object: %o', { a: 1 }));
14// 'Object: { a: 1 }'
15
16console.log(util.format('Big: %O', { nested: { deep: 1 } }));
17// Full inspection
18
19// Integer formats
20console.log(util.format('Int: %i', 42.5));
21// 'Int: 42'
22
23// Percent sign
24console.log(util.format('100%% complete'));
25// '100% complete'
26
27// Extra arguments appended
28console.log(util.format('Hello', 'World', '!'));
29// 'Hello World !'
30
31// With options
32console.log(
33 util.formatWithOptions(
34 { colors: true },
35 'Data: %O',
36 { nested: { value: 42 } }
37 )
38);inspect#
1const util = require('util');
2
3const complexObject = {
4 name: 'Test',
5 nested: {
6 level1: {
7 level2: {
8 level3: {
9 value: 'deep',
10 },
11 },
12 },
13 },
14 array: [1, 2, 3, 4, 5],
15 fn: function myFunc() {},
16 date: new Date(),
17};
18
19// Basic inspection
20console.log(util.inspect(complexObject));
21
22// With options
23console.log(util.inspect(complexObject, {
24 depth: null, // Unlimited depth
25 colors: true, // Colorize output
26 showHidden: true, // Show non-enumerable
27 maxArrayLength: 10,
28 maxStringLength: 100,
29 breakLength: 80,
30 compact: false,
31 sorted: true,
32}));
33
34// Custom inspect
35class MyClass {
36 constructor(value) {
37 this.value = value;
38 this.secret = 'hidden';
39 }
40
41 [util.inspect.custom](depth, options) {
42 return `MyClass<${this.value}>`;
43 }
44}
45
46const instance = new MyClass(42);
47console.log(util.inspect(instance));
48// 'MyClass<42>'debuglog#
1const util = require('util');
2
3// Create debug logger
4const debug = util.debuglog('myapp');
5
6// Only logs when NODE_DEBUG=myapp
7debug('Starting application');
8debug('Config: %o', { port: 3000 });
9
10// Multiple sections
11const dbDebug = util.debuglog('myapp:db');
12const apiDebug = util.debuglog('myapp:api');
13
14dbDebug('Connecting to database');
15apiDebug('Processing request');
16
17// Run with: NODE_DEBUG=myapp node app.js
18// Or: NODE_DEBUG=myapp:* node app.js (all myapp logs)
19
20// Check if enabled
21const log = util.debuglog('myapp', (fn) => {
22 // Called when logging is enabled
23 console.log('Debug logging enabled');
24});types#
1const util = require('util');
2
3// Type checking
4util.types.isDate(new Date()); // true
5util.types.isRegExp(/pattern/); // true
6util.types.isMap(new Map()); // true
7util.types.isSet(new Set()); // true
8util.types.isPromise(Promise.resolve()); // true
9
10// ArrayBuffer types
11util.types.isArrayBuffer(new ArrayBuffer(8)); // true
12util.types.isTypedArray(new Uint8Array(8)); // true
13util.types.isUint8Array(new Uint8Array(8)); // true
14
15// Error types
16util.types.isNativeError(new Error()); // true
17util.types.isNativeError({ message: 'fake' }); // false
18
19// Async types
20util.types.isAsyncFunction(async () => {}); // true
21util.types.isGeneratorFunction(function* () {}); // true
22
23// Proxy
24const proxy = new Proxy({}, {});
25util.types.isProxy(proxy); // true
26
27// SharedArrayBuffer (if available)
28if (typeof SharedArrayBuffer !== 'undefined') {
29 util.types.isSharedArrayBuffer(new SharedArrayBuffer(8)); // true
30}deprecate#
1const util = require('util');
2
3// Mark function as deprecated
4const oldFunction = util.deprecate(
5 function oldWay(x) {
6 return x * 2;
7 },
8 'oldWay() is deprecated. Use newWay() instead.',
9 'DEP0001'
10);
11
12// Warning printed once on first call
13oldFunction(5); // Prints deprecation warning
14oldFunction(10); // No warning (already shown)
15
16// Mark method
17class OldAPI {
18 constructor() {
19 this.oldMethod = util.deprecate(
20 this._oldMethod.bind(this),
21 'oldMethod() is deprecated'
22 );
23 }
24
25 _oldMethod() {
26 return 'old';
27 }
28
29 newMethod() {
30 return 'new';
31 }
32}
33
34// Suppress warnings
35// NODE_OPTIONS=--no-deprecation node app.js
36// Or: process.noDeprecation = true;inherits (Legacy)#
1const util = require('util');
2
3// Legacy inheritance (prefer class syntax)
4function Animal(name) {
5 this.name = name;
6}
7
8Animal.prototype.speak = function () {
9 console.log(this.name + ' makes a sound.');
10};
11
12function Dog(name) {
13 Animal.call(this, name);
14}
15
16util.inherits(Dog, Animal);
17
18Dog.prototype.speak = function () {
19 console.log(this.name + ' barks.');
20};
21
22// Modern equivalent
23class Animal2 {
24 constructor(name) {
25 this.name = name;
26 }
27 speak() {
28 console.log(this.name + ' makes a sound.');
29 }
30}
31
32class Dog2 extends Animal2 {
33 speak() {
34 console.log(this.name + ' barks.');
35 }
36}getSystemErrorName#
1const util = require('util');
2const fs = require('fs');
3
4// Get system error name from errno
5fs.access('/nonexistent', (err) => {
6 if (err) {
7 console.log('Error code:', err.code);
8 console.log('Errno:', err.errno);
9 console.log('System name:', util.getSystemErrorName(err.errno));
10 // ENOENT
11 }
12});
13
14// Common error codes
15const errors = [-2, -13, -17, -28];
16errors.forEach((errno) => {
17 console.log(errno, '->', util.getSystemErrorName(errno));
18});
19// -2 -> ENOENT (No such file)
20// -13 -> EACCES (Permission denied)
21// -17 -> EEXIST (File exists)
22// -28 -> ENOSPC (No space left)parseArgs#
1const { parseArgs } = require('util');
2
3// Parse command line arguments
4const options = {
5 name: { type: 'string', short: 'n' },
6 verbose: { type: 'boolean', short: 'v', default: false },
7 count: { type: 'string', short: 'c' },
8};
9
10const { values, positionals } = parseArgs({
11 options,
12 allowPositionals: true,
13});
14
15console.log(values);
16// { name: 'test', verbose: true, count: '5' }
17console.log(positionals);
18// ['file1.txt', 'file2.txt']
19
20// Usage: node app.js --name test -v --count 5 file1.txt file2.txt
21
22// With strict mode
23try {
24 parseArgs({
25 options,
26 strict: true, // Throw on unknown options
27 });
28} catch (err) {
29 console.error('Invalid arguments:', err.message);
30}TextEncoder/TextDecoder#
1const util = require('util');
2
3// Encode string to Uint8Array
4const encoder = new util.TextEncoder();
5const encoded = encoder.encode('Hello, World!');
6console.log(encoded);
7// Uint8Array [ 72, 101, 108, 108, 111, ... ]
8
9// Decode Uint8Array to string
10const decoder = new util.TextDecoder('utf-8');
11const decoded = decoder.decode(encoded);
12console.log(decoded);
13// 'Hello, World!'
14
15// With different encodings
16const utf16Decoder = new util.TextDecoder('utf-16le');
17
18// Stream decoding
19const streamDecoder = new util.TextDecoder('utf-8', { stream: true });
20// Handles incomplete multi-byte sequencesBest Practices#
Promisify:
✓ Convert callback APIs
✓ Use with async/await
✓ Define custom behavior
✓ Handle multiple values
Debugging:
✓ Use debuglog for dev
✓ Use inspect for logging
✓ Add custom inspect methods
✓ Format with colors
Type Checking:
✓ Use util.types
✓ Check native types
✓ Validate inputs
✓ Handle edge cases
Avoid:
✗ Using inherits (use class)
✗ Ignoring deprecation
✗ Complex format strings
✗ Excessive inspection depth
Conclusion#
The util module provides essential utilities for Node.js development. Use promisify for callback-to-promise conversion, debuglog for conditional logging, and inspect for detailed object visualization. The types namespace offers reliable type checking, and parseArgs simplifies CLI argument parsing.