assert.partialDeepStrictEqual()
Checks that the expected value is a deep subset of the actual value, ignoring extra properties.
assert.partialDeepStrictEqual(actual, expected[, message])- Added in Node.js v23.4.0, v22.13.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$actual | any | The full value produced by the code under test. May contain properties not present in expected. |
$expected | any | The subset that must be present in actual. Only properties that exist here are compared. |
$messageoptional | string | Error | Function | Error message, an Error instance to throw instead, or a function called on failure. |
Errors
Throws an AssertionError with code ERR_ASSERTION when a property present in expected is missing from actual or differs from it; if message is an Error instance, that error is thrown instead.
Changelog
- PHP v25.0.0Promises are no longer considered equal unless they are the same instance.
- PHP v25.0.0Invalid dates are now considered equal.
- PHP v24.0.0, v22.17.0partialDeepStrictEqual is now Stable. Previously it had been Experimental.
assert.partialDeepStrictEqual() answers the question deepStrictEqual() cannot: does this big object contain the bits I care about? Only the properties present in expected are compared, so timestamps, generated ids, and every other volatile field in actual are simply ignored. It is a strict superset of deepStrictEqual — anything that passes the full comparison passes this one too.
How the matching works
- Primitives are compared with
Object.is(), exactly as in the strict comparisons. - Type tags must match, so an
Arraynever satisfies a plain-object expectation. - Prototypes are not compared — the one place it deliberately relaxes
deepStrictEqual's rules, which is why a class instance can be matched against an object literal. - Arrays are matched as subsets:
['admin']is satisfied by['admin', 'dev'].
Stability
It landed in v23.4.0 and v22.13.0 as Experimental and became Stable in v24.0.0 and v22.17.0. On older releases the function simply does not exist, so guard with typeof assert.partialDeepStrictEqual === 'function' if you support Node 20.
Example
When to use it
- Assert the interesting fields of an API response while ignoring request ids and timestamps
- Check that a log entry carries the right level and message without pinning the whole record
- Verify a config object contains the overrides you applied on top of large defaults
Frequently asked questions
Is assert.partialDeepStrictEqual() still experimental?
No — it became Stable in v24.0.0 and v22.17.0, having shipped as Experimental in v23.4.0 and v22.13.0. It does not exist at all on Node 20 or earlier, so feature-detect it if you support those versions.
How do I assert only part of an object in a Node test?
Pass the full value as actual and an object containing just the keys you care about as expected: assert.partialDeepStrictEqual(response, { status: 200 }). Keys absent from expected are ignored, so timestamps and generated ids do not break the test.
Does partialDeepStrictEqual check array order?
No, arrays are matched as subsets, so [1, 2] is satisfied by [3, 1, 2] and position is not pinned. Use assert.deepStrictEqual() when the exact ordering is part of what you are testing.
More examples
Asserting a response without pinning volatile fields
The partial assertion covers the deterministic business fields while the generated id and timestamp are checked separately by shape. Note that the items entry omits price entirely and still matches, because only keys present in the expected object are compared.
const assert = require('node:assert');
function createOrder(items) {
return {
id: `ord_${Math.random().toString(36).slice(2, 10)}`,
createdAt: new Date(),
status: 'pending',
items,
total: items.reduce((sum, i) => sum + i.price * i.qty, 0),
};
}
const order = createOrder([{ sku: 'A1', price: 250, qty: 2 }]);
// deepStrictEqual is impossible here — id and createdAt change every run.
assert.partialDeepStrictEqual(order, {
status: 'pending',
total: 500,
items: [{ sku: 'A1', qty: 2 }],
});
// Pin the volatile fields by shape instead of by value.
assert.match(order.id, /^ord_[a-z0-9]{8}$/);
assert.ok(order.createdAt instanceof Date);
console.log('order verified');Prototypes are ignored, unlike deepStrictEqual
This is the practical reason to reach for the partial form on ORM models and class-based domain objects: it skips the prototype check that makes deepStrictEqual reject a class instance compared against an object literal. Type tags are still checked, so an array would not match a plain-object expectation.
const assert = require('node:assert');
class Session {
constructor(userId) {
this.userId = userId;
this.createdAt = Date.now();
this.scopes = ['read', 'write'];
}
}
const session = new Session(9);
// deepStrictEqual rejects this — Session !== Object.
try {
assert.deepStrictEqual(session, { userId: 9 });
} catch (err) {
console.log('deepStrictEqual ->', err.code);
}
// partialDeepStrictEqual does not compare prototypes.
assert.partialDeepStrictEqual(session, { userId: 9, scopes: ['read'] });
console.log('partial match against a class instance passed');Guarding for older Node versions
The typeof guard turns an unsupported runtime into a skipped test rather than a TypeError, which matters because the function is absent entirely before v22.13.0 and v23.4.0. The assertion itself ignores pid, time and the stack string while still pinning the error code nested two levels down.
const test = require('node:test');
const assert = require('node:assert/strict');
const hasPartial = typeof assert.partialDeepStrictEqual === 'function';
test('log entry carries the right level', { skip: hasPartial ? false : 'needs Node >= 22.13' }, () => {
const entry = {
level: 'error',
msg: 'upload failed',
pid: process.pid,
time: Date.now(),
err: { code: 'EPIPE', stack: '...' },
};
assert.partialDeepStrictEqual(entry, {
level: 'error',
msg: 'upload failed',
err: { code: 'EPIPE' },
});
});
// $ node --test
// ✓ log entry carries the right level (0.7ms)
// (on Node 20: − log entry carries the right level # SKIP needs Node >= 22.13)
Discussion