Bare Assert
bare-assert is a minimalist assertion library for JavaScript, designed to be lightweight and efficient. It provides fundamental assertion utilities like `ok`, `equal`, and `deepEqual`, suitable for testing or validating conditions in various JavaScript environments. The current stable version is 1.2.0, released in December 2025. This library is part of the broader Holepunchto 'bare' ecosystem, which focuses on small, modular JavaScript runtimes for desktop and mobile, suggesting an emphasis on performance and a reduced footprint. Its release cadence appears to be on an 'as-needed' basis, with updates roughly annually or semi-annually. A key differentiator is its 'bare-bones' philosophy, offering essential assertions without the extensive feature sets found in larger frameworks like Chai or Node.js's built-in `assert` module. It ships with TypeScript types, leveraging TypeScript's `asserts` keyword for enhanced type narrowing.
Common errors
-
TypeError: assert is not a function
cause Attempting to call `require('bare-assert').assert()` or `import { assert } from 'bare-assert'; assert()`. The primary `assert` object is the default export, not a named property on the module.fixFor CommonJS, use `const assert = require('bare-assert'); assert.ok(...)`. For ESM, use `import assert from 'bare-assert'; assert.ok(...)` or `import { ok } from 'bare-assert'; ok(...)`. -
Property 'someProperty' does not exist on type 'unknown'.
cause Trying to access properties on a value after an assertion function, but TypeScript's type narrowing has not been applied, often due to incorrect usage of assertion functions or type guards.fixEnsure the assertion function has a proper `asserts value is Type` signature and that the code path after the assertion only executes if the assertion passes. For example: `function assertHasProperty(obj: unknown): asserts obj is { someProperty: any } { /* ... */ }`.
Warnings
- gotcha bare-assert is designed as a minimalist library. Users accustomed to feature-rich assertion libraries like Chai or Jest's expect API may find its functionality limited. It focuses on core assertions (e.g., ok, equal, deepEqual) without advanced matchers, spies, or mock capabilities.
- gotcha The `asserts` keyword in TypeScript (which `bare-assert` utilizes for its type definitions) provides compile-time type narrowing, but it relies on runtime checks to guarantee types. Misunderstanding its behavior can lead to false confidence if the underlying runtime assertion logic is flawed or bypassed.
- gotcha While `bare-assert` is an assertion library for JavaScript, its origin within the Holepunchto 'bare' ecosystem suggests it might be particularly tuned for that specific runtime. Although available on npm for general use, subtle differences in environment (e.g., browser vs. Node.js) might behave differently than Node.js's native `assert` module.
Install
-
npm install bare-assert -
yarn add bare-assert -
pnpm add bare-assert
Imports
- assert
import { assert } from 'bare-assert'; // 'assert' is the default export, not a named export. Named imports are for individual methods like 'ok' or 'equal'.import assert from 'bare-assert';
- ok
const ok = require('bare-assert').ok; // While functional, 'import' is preferred in modern JavaScript and TypeScript projects. import assert from 'bare-assert'; assert.ok(value); // This is also correct but `ok` can be directly imported for brevity.import { ok } from 'bare-assert'; - CommonJS require
const { assert } = require('bare-assert'); // This would attempt to destructure a named 'assert' export, which doesn't exist as the main assert object is the default export.const assert = require('bare-assert');
Quickstart
import assert, { ok, equal, deepEqual } from 'bare-assert';
function processData(data: unknown): asserts data is { id: number, name: string } {
ok(data !== null && typeof data === 'object', 'Data must be an object.');
equal(typeof (data as any).id, 'number', 'Data must have a numeric ID.');
equal(typeof (data as any).name, 'string', 'Data must have a string name.');
}
try {
const validData = { id: 123, name: 'Alice' };
processData(validData);
console.log('Valid data processed:', validData.name); // TypeScript knows validData is now { id: number, name: string }
ok(1 + 1 === 2, 'Arithmetic works!');
equal('hello', 'hello', 'Strings should be equal.');
deepEqual({ a: 1, b: { c: 2 } }, { a: 1, b: { c: 2 } }, 'Deep equality works for objects.');
const invalidData = { id: 456, title: 'Invalid' };
// This will throw an error and be caught
// processData(invalidData); // Uncomment to see error
} catch (error: any) {
console.error('Assertion failed:', error.message);
}
// Example of using an individual named export
function checkConfig(config: { API_KEY?: string }): asserts config is { API_KEY: string } {
ok(config.API_KEY, 'API_KEY must be defined in config.');
}
const myConfig = { API_KEY: process.env.MY_API_KEY ?? 'default-key' };
try {
checkConfig(myConfig);
console.log('API Key is:', myConfig.API_KEY);
} catch (error: any) {
console.error('Config error:', error.message);
}