Core 10 util
Core 10 - Util Module¶
Basic Idea¶
util is Node's utility drawer Random useful functions that didn't fit anywhere else Promisify , inspect , format , deprecate - the everyday helpers
util.promisify() - Callback to Promise¶
const util = require('util')
const fs = require('fs')
// convert callback-based function to promise-based
const readFile = util.promisify(fs.readFile)
async function main() {
try {
const data = await readFile('config.json', 'utf-8')
console.log('config:', JSON.parse(data))
} catch (err) {
console.error('failed to read config:', err.message)
}
}
promisify() wraps any function that follows the Node callback convention (err, value) => {} - first argument is error , second is result If the callback is called with multiple results , promisify returns an array
// functions with multiple callback arguments
const crypto = require('crypto')
const pbkdf2 = util.promisify(crypto.pbkdf2)
const key = await pbkdf2('password', 'salt', 100000, 64, 'sha512')
// Buffer - single result (others are dropped)
// custom promisify - define custom behavior
const fn = util.promisify(someFunction)
// if someFunction[util.customPromisifyArgs] is set, it maps argument names
Note: in modern Node (14+) , use fs/promises , timers/promises , etc instead of promisifying promisify() is for libraries that haven't updated to native promises
util.callbackify() - Promise to Callback¶
const util = require('util')
async function fetchData() {
const response = await fetch('https://api.example.com/data')
return response.json()
}
// convert to callback-style for compatibility
const fetchDataCallback = util.callbackify(fetchData)
fetchDataCallback((err, data) => {
if (err) {
console.error('fetch failed:', err)
return
}
console.log('data:', data)
})
Much less common than promisify Useful when you need to adapt a promise-based API to callback-expecting code If the promise rejects with null or undefined , the error becomes a regular Error
util.inspect() - Object Inspection¶
const util = require('util')
const complexObj = {
name: 'server',
config: { port: 3000, host: '0.0.0.0' },
nested: { deep: { deeper: { value: 'secret' } } },
buffer: Buffer.from('hello'),
date: new Date()
}
// default - nice formatting
console.log(util.inspect(complexObj))
// control depth
console.log(util.inspect(complexObj, { depth: null, colors: true }))
// show hidden (non-enumerable) properties
console.log(util.inspect(complexObj, { showHidden: true }))
// compact output
console.log(util.inspect(complexObj, { compact: true }))
// custom inspection
const customObj = {
[util.inspect.custom]() {
return '<CustomObject: hidden>'
}
}
console.log(util.inspect(customObj)) // '<CustomObject: hidden>'
inspect() is what console.log() calls internally Use it when you need fine-grained control over how objects are displayed Setting depth: null shows everything - dangerous with circular references (infinite loop)
util.format() - printf-Style Formatting¶
const util = require('util')
// %s - string
console.log(util.format('hello %s', 'world')) // 'hello world'
// %d - number
console.log(util.format('count: %d', 42)) // 'count: 42'
// %i - integer
console.log(util.format('port: %i', 8080)) // 'port: 8080'
// %f - float
console.log(util.format('ratio: %f', 3.14159)) // 'ratio: 3.14159'
// %j - JSON
console.log(util.format('config: %j', { port: 3000 })) // 'config: {"port":3000}'
// %o - optimized object representation
// %O - generic object representation
// %% - literal percent sign
console.log(util.format('completion: %d%%', 75)) // 'completion: 75%'
Less useful now with template literals (\hello ${world}`) Still handy for log formatters where you need consistent output%jcallsJSON.stringify()` - will throw on circular references
util.types - Type Checking¶
const util = require('util')
console.log(util.types.isDate(new Date())) // true
console.log(util.types.isRegExp(/test/)) // true
console.log(util.types.isArrayBuffer(new ArrayBuffer(8))) // true
console.log(util.types.isSet(new Set([1, 2, 3]))) // true
console.log(util.types.isMap(new Map())) // true
console.log(util.types.isPromise(Promise.resolve())) // true
console.log(util.types.isNativeError(new Error())) // true
console.log(util.types.isProxy({})) // false (can't detect proxy)
// built-in types only - not classes from your code
console.log(util.types.isTypedArray(new Uint8Array())) // true
More specific than typeof or instanceof util.types.isProxy() can't detect proxies - that's by design (proxies are transparent) Use for proper type discrimination when building libraries
util.deprecate() - Marking Deprecated Functions¶
const util = require('util')
// old API that you want to phase out
function oldConnect(config) {
// ...
}
const connect = util.deprecate(oldConnect, 'connect() is deprecated. Use createConnection() instead.')
// when called:
connect({ host: 'localhost' })
// (node:12345) DeprecationWarning: connect() is deprecated. Use createConnection() instead.
// custom deprecation code
const connectV2 = util.deprecate(
oldConnect,
'connect() is deprecated. Use connectV2() instead.',
'MYAPP001' // custom code for filtering
)
// (node:12345) [MYAPP001] DeprecationWarning: connect() is deprecated. Use connectV2() instead.
// suppress deprecation warnings
// NODE_OPTIONS='--no-deprecation' node app.js
Deprecation warnings print to stderr - once per method name per process Use custom codes (e.g., 'MYAPP001') so consumers can suppress specific warnings Don't use deprecate() for internal-only functions - it's a public API tool
util.inherits() - Legacy (Don't Use)¶
const util = require('util')
const EventEmitter = require('events')
// OLD WAY - pre-ES6 classes
function MyClass() {
EventEmitter.call(this)
}
util.inherits(MyClass, EventEmitter)
// MODERN WAY
class MyClass extends EventEmitter {}
util.inherits() was the pre-ES6 way to do inheritance Nobody should use this in 2025+ Use class extends syntax - cleaner , faster , and supported since Node 4
util.TextEncoder and util.TextDecoder¶
const { TextEncoder, TextDecoder } = require('util')
const encoder = new TextEncoder()
const bytes = encoder.encode('hello') // Uint8Array
console.log(bytes) // Uint8Array(5) [104, 101, 108, 108, 111]
const decoder = new TextDecoder()
const str = decoder.decode(bytes)
console.log(str) // 'hello'
Available globally in Node 11+ and all modern browsers Use instead of Buffer.from(str, 'utf-8').toString() for encoding-agnostic code TextEncoder/TextDecoder are faster than Buffer for pure text operations
Summary¶
promisify()for adapting legacy callback APIsinspect()for detailed object inspection ,format()for printf-style stringstypesfor reliable type checking of built-in typesdeprecate()for marking public API methods as deprecatedinherits()is dead - useclass extendsinstead
Prerequisites¶
next -> core_11_url.md