Skip to content
JavaScript Basics: Classify Built-In Values with util.types

JavaScript Basics: Classify Built-In Values with util.types

October 27, 2026

Values from another JavaScript realm can fail ordinary instanceof checks. Node’s util.types offers built-in type predicates for diagnostic and interoperability code. A trusted fixed VM expression creates a cross-realm Date for comparison.

Prepare a scratch directory

Tested on Linux with Node.js v24.19.0. You need the named runtime, Bash, a text editor, and the standard mktemp, rm, and rmdir utilities. The .mjs extension selects ES modules. Assertions check the demonstrated behavior; no npm packages or remote services are needed.

Keep using the same terminal. Stop if setup fails, before saving the source:

start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1

Run the example

Save this as demonstrate-util-types.mjs:

import assert from 'node:assert/strict';
import { types } from 'node:util';
import vm from 'node:vm';

const foreignDate = vm.runInNewContext('new Date(0)');
assert.equal(foreignDate instanceof Date, false);
assert.equal(types.isDate(foreignDate), true);
console.log('Foreign Date instanceof local Date:', foreignDate instanceof Date);
console.log('Foreign Date recognized by util.types:', types.isDate(foreignDate));

const disguised = { [Symbol.toStringTag]: 'Map' };
assert.equal(Object.prototype.toString.call(disguised), '[object Map]');
assert.equal(types.isMap(disguised), false);
assert.equal(types.isMap(new Map()), true);
console.log('Display tag can say:', Object.prototype.toString.call(disguised));
console.log('Disguised value is a Map:', types.isMap(disguised));

const bytes = new Uint8Array(4);
const view = new DataView(bytes.buffer);
assert.equal(types.isTypedArray(bytes), true);
assert.equal(types.isTypedArray(view), false);
assert.equal(types.isArrayBufferView(view), true);
console.log('DataView is typed array:', types.isTypedArray(view));
console.log('DataView is buffer view:', types.isArrayBufferView(view));

Run it:

node demonstrate-util-types.mjs

Observed output:

Foreign Date instanceof local Date: false
Foreign Date recognized by util.types: true
Display tag can say: [object Map]
Disguised value is a Map: false
DataView is typed array: false
DataView is buffer view: true

Read the result

The foreign Date has another realm’s prototype, so the local constructor’s instanceof check fails. The built-in predicate still recognizes the value. A custom string tag can alter a display label without creating a real Map. The final checks distinguish typed arrays from the broader family of ArrayBuffer views, which also includes DataView.

Apply it carefully

These predicates classify values; they do not validate application schemas, guarantee safe methods, or inspect every nested member. Cross-realm objects can still need normalization before use. The VM call executes only a fixed trusted expression here; Node’s VM API should not be used as an untrusted-code security boundary. Prefer simple language checks such as Array.isArray when they already express the contract you need.

The official reference describes the API and its options. The checks above cover the specific fixture, not every possible input or environment.

Clean up

Remove the source and then the empty practice directory:

rm -- demonstrate-util-types.mjs
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dir

If the directory is not empty, inspect the remaining files rather than deleting unknown contents.

Acknowledgements

This post was created with assistance from AI.

Last updated on