Constantinople Constant Expression Evaluator
Constantinople is a JavaScript utility package, currently at stable version 4.0.1, designed to determine if a given JavaScript expression evaluates to a constant. It parses the expression into an Abstract Syntax Tree (AST) using Babylon (now part of Babel's parser) to analyze its predictability. The library prioritizes safety, conservatively returning `false` if there's any uncertainty, ensuring reliability for build tools and static analysis where incorrect constant detection could cause issues. It also provides a `toConstant` function to safely evaluate expressions identified as constant, throwing an error if the expression is not constant. The package ships with TypeScript type definitions, enhancing developer experience for TypeScript users.
Common errors
-
Expression is not constant
cause You attempted to call `isConstant.toConstant()` on an expression that the library determined was not constant.fixEnsure `isConstant()` returns `true` for an expression before calling `isConstant.toConstant()`, or wrap `isConstant.toConstant()` calls in a `try...catch` block to handle this expected error. -
SyntaxError: Unexpected token ...
cause The input string provided to `isConstant` or `isConstant.toConstant` contained a JavaScript syntax error, preventing successful parsing.fixReview and correct the syntax of the input expression string. `isConstant()` will return `false` for syntax errors, while `isConstant.toConstant()` will throw a `SyntaxError`. -
TypeError: isConstant_1.toConstant is not a function
cause You attempted to import `isConstant` as a named export (`{ isConstant }`) or `toConstant` as a top-level named export. However, `isConstant` is the default export and `toConstant` is a property of that default export.fixImport `isConstant` as a default export (`import isConstant from 'constantinople';`) and access `toConstant` as a property of the imported object (`isConstant.toConstant`). For CommonJS, use `const isConstant = require('constantinople');`.
Warnings
- gotcha Providing volatile objects like `Math` or `Date` to the optional `constants` parameter can lead to incorrect `isConstant` evaluations or unexpected `toConstant` results if methods like `Math.random()` or `Date.now()` are present in the expression. The library aims to safely *underestimate* constancy, but user-provided contexts can unintentionally override this safety.
- gotcha The `toConstant` function will throw an error if the provided expression is determined not to be constant. This behavior is by design, ensuring that only truly constant expressions are evaluated to a direct value.
- gotcha The `isConstant` function returns `false` for expressions with syntax errors rather than throwing an exception. While safe, this means a `false` return could indicate either a non-constant expression or a malformed one. `toConstant` *will* throw on syntax errors when attempting to parse and evaluate.
Install
-
npm install constantinople -
yarn add constantinople -
pnpm add constantinople
Imports
- isConstant
import { isConstant } from 'constantinople';import isConstant from 'constantinople';
- isConstant (CJS)
const { isConstant } = require('constantinople');const isConstant = require('constantinople'); - toConstant
import { toConstant } from 'constantinople';import isConstant from 'constantinople'; const result = isConstant.toConstant('some_expression');
Quickstart
import isConstant from 'constantinople';
const expression1 = '"foo" + 5';
const expression2 = 'Math.floor(10.5)';
const expression3 = 'Date.now()'; // Example of a non-constant
// Check and evaluate a simple constant string concatenation
if (isConstant(expression1)) {
console.log(`'${expression1}' is constant.`);
try {
const result = isConstant.toConstant(expression1);
console.log(`Value: ${result}`); // Expected: "foo5"
} catch (error: any) {
console.error(`Error evaluating '${expression1}':`, error.message);
}
} else {
console.log(`'${expression1}' is not constant.`);
}
console.log('---\n');
// Check and evaluate with provided constants (e.g., Math object)
// WARNING: Providing global objects like Math might lead to unexpected behavior if they contain non-constant functions like Math.random
if (isConstant(expression2, { Math: Math })) {
console.log(`'${expression2}' is constant with Math context.`);
try {
const result = isConstant.toConstant(expression2, { Math: Math });
console.log(`Value: ${result}`); // Expected: 10
} catch (error: any) {
console.error(`Error evaluating '${expression2}':`, error.message);
}
} else {
console.log(`'${expression2}' is not constant with Math context.`);
}
console.log('---\n');
// Demonstrate a non-constant expression
if (isConstant(expression3)) {
console.log(`'${expression3}' is constant.`);
} else {
console.log(`'${expression3}' is not constant.`);
try {
isConstant.toConstant(expression3); // This will throw an error
} catch (error: any) {
console.error(`Attempting to evaluate non-constant '${expression3}' throws: ${error.message}`);
}
}