← Back to README | Related: Getting Started · Static Analysis · Execution · Error Handling
Complete reference for the Typebars public API — classes, methods, types, and options.
The main engine class. Each instance has its own isolated Handlebars environment, helper registry, and LRU caches.
import { Typebars } from "typebars";new Typebars(options?: TemplateEngineOptions)| Parameter | Type | Default | Description |
|---|---|---|---|
options.astCacheSize |
number |
256 |
LRU cache size for parsed ASTs |
options.compilationCacheSize |
number |
256 |
LRU cache size for compiled Handlebars templates |
options.helpers |
HelperConfig[] |
[] |
Custom helpers to register at construction time |
const engine = new Typebars({
astCacheSize: 512,
compilationCacheSize: 512,
helpers: [
{
name: "uppercase",
fn: (value) => String(value).toUpperCase(),
params: [{ name: "value", type: { type: "string" } }],
returnType: { type: "string" },
},
],
});Built-in helpers (math, logical, map) are automatically registered before custom helpers.
Statically validates a template against an input schema and infers the output schema.
analyze(
template: TemplateInput,
inputSchema?: JSONSchema7,
options?: AnalyzeOptions,
): AnalysisResult| Parameter | Type | Description |
|---|---|---|
template |
TemplateInput |
The template to analyze |
inputSchema |
JSONSchema7 |
JSON Schema describing available variables (default: {}) |
options |
AnalyzeOptions |
Optional — identifier schemas, coercion schema, expression filtering |
Returns: AnalysisResult — { valid, diagnostics, outputSchema }
Throws: TemplateParseError on invalid syntax, UnsupportedSchemaError on if/then/else schemas.
Does not throw on validation failures — check result.valid and result.diagnostics instead.
const result = engine.analyze("{{name}}", schema);
if (result.valid) {
console.log(result.outputSchema); // { type: "string" }
} else {
console.log(result.diagnostics); // TemplateDiagnostic[]
}See Static Analysis for detailed behavior.
Like analyze() but without computing the outputSchema. Slightly lighter — useful when you only need validation.
validate(
template: TemplateInput,
inputSchema?: JSONSchema7,
options?: AnalyzeOptions,
): ValidationResultReturns: ValidationResult — { valid, diagnostics } (no outputSchema).
const result = engine.validate("{{name}}", schema);
result.valid; // boolean
result.diagnostics; // TemplateDiagnostic[]Renders a template with data. Optionally validates against a schema first.
execute(
template: TemplateInput,
data: TemplateData,
options?: ExecuteOptions,
): unknown| Parameter | Type | Description |
|---|---|---|
template |
TemplateInput |
The template to execute |
data |
TemplateData |
The data context for rendering |
options |
ExecuteOptions |
Optional — schema for pre-execution validation, identifier data, coercion, expression filtering |
Returns: The rendered value. The type depends on the template structure — see Type Preservation.
Throws:
TemplateParseErroron invalid syntaxTemplateAnalysisErrorifoptions.schemais provided and analysis failsTemplateRuntimeErroron Handlebars runtime errors
engine.execute("{{age}}", { age: 30 }); // → 30 (number)
engine.execute("Hello {{name}}", { name: "A" }); // → "Hello A" (string)
engine.execute(42, {}); // → 42 (literal passthrough)Performs both static analysis and execution in a single call. If analysis fails, execution is skipped and value is undefined.
analyzeAndExecute(
template: TemplateInput,
inputSchema: JSONSchema7,
data: TemplateData,
options?: AnalyzeAndExecuteOptions,
): { analysis: AnalysisResult; value: unknown }| Parameter | Type | Description |
|---|---|---|
template |
TemplateInput |
The template to process |
inputSchema |
JSONSchema7 |
JSON Schema describing available variables |
data |
TemplateData |
The data context for rendering |
options |
AnalyzeAndExecuteOptions |
Optional — identifiers, coercion, expression filtering |
Returns: { analysis: AnalysisResult, value: unknown } — value is undefined if analysis.valid is false.
const { analysis, value } = engine.analyzeAndExecute("{{age}}", schema, data);
analysis.outputSchema; // { type: "number" }
value; // 30Parses a template once and returns a reusable CompiledTemplate. Avoids re-parsing on repeated executions.
compile(template: TemplateInput): CompiledTemplateReturns: CompiledTemplate
Throws: TemplateParseError on invalid syntax.
const tpl = engine.compile("Hello {{name}}!");
tpl.execute({ name: "Alice" }); // → "Hello Alice!"
tpl.execute({ name: "Bob" }); // → "Hello Bob!"See Compiled Templates for detailed usage.
Checks if a template string has valid Handlebars syntax. Does not validate against a schema.
isValidSyntax(template: string): booleanengine.isValidSyntax("Hello {{name}}"); // true
engine.isValidSyntax("{{#if x}}oops{{/unless}}"); // falseSee Syntax Validation.
Registers a custom helper with type metadata for static analysis.
registerHelper(name: string, definition: HelperDefinition): thisReturns this for chaining.
engine
.registerHelper("upper", {
fn: (v) => String(v).toUpperCase(),
returnType: { type: "string" },
})
.registerHelper("lower", {
fn: (v) => String(v).toLowerCase(),
returnType: { type: "string" },
});See Custom Helpers for detailed examples.
Removes a helper (including built-in ones). Invalidates the compilation cache.
unregisterHelper(name: string): thisReturns this for chaining.
Checks whether a helper is registered on this instance.
hasHelper(name: string): booleanengine.hasHelper("add"); // true (built-in)
engine.hasHelper("custom"); // falseClears all internal caches (AST + compilation). Useful after configuration changes or to free memory.
clearCaches(): voidReturned by engine.compile(). Provides the same operations as the engine but without re-parsing.
Uses a discriminated union internally (TemplateState) with kinds: "template", "literal", "object", and "array".
execute(data: TemplateData, options?: ExecuteOptions): unknownanalyze(inputSchema: JSONSchema7, options?: AnalyzeOptions): AnalysisResultvalidate(inputSchema: JSONSchema7, options?: AnalyzeOptions): ValidationResultanalyzeAndExecute(
inputSchema: JSONSchema7,
data: TemplateData,
options?: AnalyzeAndExecuteOptions,
): { analysis: AnalysisResult; value: unknown }Note: The parameter order for
CompiledTemplatemethods differs fromTypebarsmethods — there is notemplateparameter since the template is already compiled.
The input type accepted by the template engine. A recursive union:
type TemplateInput =
| string // Handlebars template (parsed and executed)
| number // Literal passthrough
| boolean // Literal passthrough
| null // Literal passthrough
| TemplateInputArray // Array where each element is a TemplateInput
| TemplateInputObject // Object where each property is a TemplateInputSee Templates for object and array template behavior.
The data context accepted by execute() and analyzeAndExecute():
type TemplateData =
| string
| number
| boolean
| null
| undefined
| Record<string, unknown>interface TemplateInputObject {
[key: string]: TemplateInput;
}type TemplateInputArray = TemplateInput[];Returned by analyze() and analyzeAndExecute():
interface AnalysisResult {
valid: boolean; // true if no error-severity diagnostics
diagnostics: TemplateDiagnostic[]; // all diagnostics (errors + warnings)
outputSchema: JSONSchema7; // inferred output type
}Returned by validate():
interface ValidationResult {
valid: boolean;
diagnostics: TemplateDiagnostic[];
}A structured diagnostic object. See Diagnostics for full details.
interface TemplateDiagnostic {
severity: "error" | "warning";
code: DiagnosticCode;
message: string;
loc?: {
start: { line: number; column: number };
end: { line: number; column: number };
};
source?: string;
details?: DiagnosticDetails;
}A union type of all possible diagnostic codes:
type DiagnosticCode =
| "UNKNOWN_PROPERTY"
| "TYPE_MISMATCH"
| "MISSING_ARGUMENT"
| "UNKNOWN_HELPER"
| "UNANALYZABLE"
| "MISSING_IDENTIFIER_SCHEMAS"
| "UNKNOWN_IDENTIFIER"
| "IDENTIFIER_PROPERTY_NOT_FOUND"
| "PARSE_ERROR"
| "ROOT_PATH_TRAVERSAL";See Diagnostic Codes for descriptions of each code.
Optional structured context attached to diagnostics:
interface DiagnosticDetails {
path?: string;
helperName?: string;
expected?: string;
actual?: string;
availableProperties?: string[];
identifier?: number;
}Passed to the Typebars constructor:
interface TemplateEngineOptions {
astCacheSize?: number; // LRU cache for parsed ASTs (default: 256)
compilationCacheSize?: number; // LRU cache for Handlebars compilations (default: 256)
helpers?: HelperConfig[]; // Custom helpers to register at construction
}Passed to analyze(), validate(), and the analysis portion of analyzeAndExecute():
interface AnalyzeOptions {
identifierSchemas?: Record<number, JSONSchema7>;
coerceSchema?: JSONSchema7;
excludeTemplateExpression?: boolean;
}| Field | Description | Docs |
|---|---|---|
identifierSchemas |
Schemas by identifier number for the {{key:N}} syntax |
Identifiers |
coerceSchema |
Explicit coercion schema overriding auto-detection for static literals | coerceSchema |
excludeTemplateExpression |
When true, exclude entries containing {{…}} from the output |
excludeTemplateExpression |
Passed to execute():
interface ExecuteOptions {
schema?: JSONSchema7;
identifierSchemas?: Record<number, JSONSchema7>;
identifierData?: Record<number, Record<string, unknown>>;
coerceSchema?: JSONSchema7;
excludeTemplateExpression?: boolean;
}| Field | Description | Docs |
|---|---|---|
schema |
When provided, runs analyze() before execution and throws TemplateAnalysisError on failure |
Error Handling |
identifierSchemas |
Schemas by identifier (for pre-execution analysis) | Identifiers |
identifierData |
Data by identifier number | Identifiers |
coerceSchema |
Output type coercion for static literals | coerceSchema |
excludeTemplateExpression |
Exclude entries with Handlebars expressions | excludeTemplateExpression |
Passed to analyzeAndExecute():
interface AnalyzeAndExecuteOptions {
identifierSchemas?: Record<number, JSONSchema7>;
identifierData?: Record<number, Record<string, unknown>>;
coerceSchema?: JSONSchema7;
excludeTemplateExpression?: boolean;
}Combines the analysis and execution options (except schema, which is implicit).
The definition object passed to registerHelper():
interface HelperDefinition {
fn: (...args: unknown[]) => unknown;
params?: HelperParam[];
returnType?: JSONSchema7;
description?: string;
}| Field | Required | Description |
|---|---|---|
fn |
✅ | The helper implementation function |
params |
❌ | Parameter definitions for static analysis |
returnType |
❌ | JSON Schema of the return value (used for output type inference) |
description |
❌ | Human-readable description |
Used in TemplateEngineOptions.helpers — a HelperDefinition with a required name:
interface HelperConfig extends HelperDefinition {
name: string;
}Describes a single helper parameter:
interface HelperParam {
name: string;
type?: JSONSchema7;
description?: string;
optional?: boolean;
}| Field | Description |
|---|---|
name |
Parameter name (used in diagnostic messages) |
type |
JSON Schema the argument must conform to (for type checking) |
description |
Human-readable description |
optional |
When true, the argument is not required |
A type-safe factory function that infers TypeScript types for the fn arguments from the params JSON Schemas:
import { defineHelper } from "typebars";
const helper = defineHelper({
name: "concat",
params: [
{ name: "a", type: { type: "string" } },
{ name: "b", type: { type: "string" } },
] as const, // ← `as const` is required for type inference
fn: (a, b) => `${a}${b}`, // TypeScript infers: a: string, b: string
returnType: { type: "string" },
});Signature:
function defineHelper<P extends readonly TypedHelperParam[]>(
config: TypedHelperConfig<P>,
): HelperConfigSee Custom Helpers — defineHelper for detailed examples.
All error classes are exported from typebars. See Error Handling for detailed descriptions.
import {
TemplateError,
TemplateParseError,
TemplateAnalysisError,
TemplateRuntimeError,
UnsupportedSchemaError,
} from "typebars";| Class | Thrown When | Key Properties |
|---|---|---|
TemplateError |
Base class — not thrown directly | message |
TemplateParseError |
Invalid Handlebars syntax | message, loc? |
TemplateAnalysisError |
execute() with schema option fails validation |
diagnostics, errors, warnings, errorCount, warningCount, toJSON() |
TemplateRuntimeError |
Handlebars runtime failure | message |
UnsupportedSchemaError |
Schema uses if/then/else |
message |
Exported utility functions for narrowing TemplateInput values:
import { isArrayInput } from "typebars";| Function | Description |
|---|---|
isArrayInput(value) |
Returns true if the value is a TemplateInputArray |
Important: Always check
isArrayInput()before checking for objects, because arrays are alsotypeof "object"in JavaScript.
The following type guards are available from the source module but not re-exported from the package entry point:
| Function | Description |
|---|---|
isLiteralInput(value) |
Returns true if the value is number, boolean, or null |
isObjectInput(value) |
Returns true if the value is a TemplateInputObject (non-array object) |
Everything exported from the typebars package entry point:
// Classes
export { Typebars } from "./typebars";
// Types
export type { AnalyzeOptions } from "./analyzer";
export type {
TemplateData,
TemplateInput,
TemplateInputArray,
} from "./types";
// Functions
export { defineHelper, isArrayInput } from "./types";
// Errors
export {
TemplateError,
TemplateParseError,
TemplateAnalysisError,
TemplateRuntimeError,
UnsupportedSchemaError,
} from "./errors";- Getting Started — installation and quick start
- Static Analysis — detailed analysis behavior
- Execution — type preservation and compiled templates
- Error Handling — error hierarchy and diagnostics