Expressions
Complete reference for all expression types in Constela
Overview
Expressions are the way to work with dynamic values in Constela. They can represent literal values, state access, variable access, and computed values.
Literal Expression
Represents a static, constant value.
{ "expr": "lit", "value": "Hello, World!" }
{ "expr": "lit", "value": 42 }
{ "expr": "lit", "value": true }
{ "expr": "lit", "value": ["a", "b", "c"] }| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "lit" | Yes | - | Expression type identifier. |
| value | any | Yes | - | The literal value (string, number, boolean, array, or object). |
State Expression
Accesses a value from the application state.
{ "expr": "state", "name": "count" }
{ "expr": "state", "name": "user" }| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "state" | Yes | - | Expression type identifier. |
| name | string | Yes | - | Name of the state field to access. |
Tip
To access nested properties of a state field, use the get expression instead.
Nested Property Access
Use the get expression to access properties within state objects:
// Access state.user.profile.name
{
"expr": "get",
"base": { "expr": "state", "name": "user" },
"path": "profile.name"
}
// Access state.settings.theme
{
"expr": "get",
"base": { "expr": "state", "name": "settings" },
"path": "theme"
}Variable Expression
Accesses a loop variable or component prop.
{ "expr": "var", "name": "item" }
{ "expr": "var", "name": "user", "path": "email" }| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "var" | Yes | - | Expression type identifier. |
| name | string | Yes | - | Name of the variable (from each loop's 'as' or component props). |
| path | string | No | - | Dot-notation path for nested property access. |
Usage in Each Loop
{
"kind": "each",
"items": { "expr": "state", "name": "users" },
"as": "user",
"index": "i",
"body": {
"kind": "text",
"value": { "expr": "var", "name": "user", "path": "name" }
}
}Binary Expression
Computes a value from two operands and an operator.
{
"expr": "bin",
"op": "+",
"left": { "expr": "state", "name": "count" },
"right": { "expr": "lit", "value": 1 }
}| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "bin" | Yes | - | Expression type identifier. |
| op | string | Yes | - | Binary operator (see operators table below). |
| left | Expression | Yes | - | Left operand expression. |
| right | Expression | Yes | - | Right operand expression. |
Binary Operators
| Operator | Description | Example |
|---|---|---|
+ | Addition / String concatenation | 5 + 3 = 8, "a" + "b" = "ab" |
- | Subtraction | 5 - 3 = 2 |
* | Multiplication | 5 * 3 = 15 |
/ | Division | 6 / 3 = 2 |
== | Equality | 5 == 5 is true |
!= | Inequality | 5 != 3 is true |
< | Less than | 3 < 5 is true |
<= | Less than or equal | 3 <= 3 is true |
> | Greater than | 5 > 3 is true |
>= | Greater than or equal | 5 >= 5 is true |
&& | Logical AND | true && false is false |
|| | Logical OR | true || false is true |
Complex Expression Example
{
"expr": "bin",
"op": "&&",
"left": {
"expr": "bin",
"op": ">",
"left": { "expr": "state", "name": "count" },
"right": { "expr": "lit", "value": 0 }
},
"right": {
"expr": "bin",
"op": "<",
"left": { "expr": "state", "name": "count" },
"right": { "expr": "lit", "value": 100 }
}
}This evaluates to true when count > 0 && count < 100.
Not Expression
Negates a boolean expression.
{
"expr": "not",
"operand": { "expr": "state", "name": "isLoading" }
}| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "not" | Yes | - | Expression type identifier. |
| operand | Expression | Yes | - | Expression to negate (should evaluate to boolean). |
Example
{
"kind": "if",
"condition": {
"expr": "not",
"operand": { "expr": "state", "name": "isHidden" }
},
"then": {
"kind": "text",
"value": { "expr": "lit", "value": "Visible content" }
}
}Param Expression
Accesses action parameters (used inside action steps).
{ "expr": "param", "name": "value" }
{ "expr": "param", "name": "event", "path": "target.value" }| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "param" | Yes | - | Expression type identifier. |
| name | string | Yes | - | Name of the action parameter. |
| path | string | No | - | Dot-notation path for nested property access. |
Usage in Actions
{
"name": "updateInput",
"steps": [
{
"do": "set",
"target": "inputValue",
"value": { "expr": "param", "name": "event", "path": "target.value" }
}
]
}Note
The param expression is primarily used within action steps to access event data or other runtime parameters.
Cond Expression
Returns different values based on a condition. Unlike the if node which controls rendering, cond evaluates to a value.
{
"expr": "cond",
"if": { "expr": "state", "name": "done" },
"then": { "expr": "lit", "value": "Completed" },
"else": { "expr": "lit", "value": "Pending" }
}| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "cond" | Yes | - | Expression type identifier. |
| if | Expression | Yes | - | Condition expression (must evaluate to boolean). |
| then | Expression | Yes | - | Expression to evaluate when condition is true. |
| else | Expression | Yes | - | Expression to evaluate when condition is false. |
Cond vs If Node
| Feature | cond Expression | if Node |
|---|---|---|
| Purpose | Compute a value | Control rendering |
| Returns | A value | A view node |
| Usage | Inside text, attributes, props | View tree |
Examples
// Conditional text label
{
"kind": "text",
"value": {
"expr": "cond",
"if": { "expr": "state", "name": "isAdmin" },
"then": { "expr": "lit", "value": "Admin Panel" },
"else": { "expr": "lit", "value": "User Dashboard" }
}
}
// Conditional CSS class
{
"kind": "element",
"tag": "div",
"props": {
"class": {
"expr": "cond",
"if": { "expr": "state", "name": "isActive" },
"then": { "expr": "lit", "value": "active" },
"else": { "expr": "lit", "value": "inactive" }
}
}
}
// Nested cond for multiple conditions
{
"expr": "cond",
"if": {
"expr": "bin",
"op": ">",
"left": { "expr": "state", "name": "score" },
"right": { "expr": "lit", "value": 80 }
},
"then": { "expr": "lit", "value": "Excellent" },
"else": {
"expr": "cond",
"if": {
"expr": "bin",
"op": ">",
"left": { "expr": "state", "name": "score" },
"right": { "expr": "lit", "value": 50 }
},
"then": { "expr": "lit", "value": "Good" },
"else": { "expr": "lit", "value": "Needs Improvement" }
}
}Tip
Use cond when you need conditional values inside text, attributes, or props. Use if nodes when you need to conditionally render entire elements.
Get Expression
Accesses properties from an object expression. Essential for working with object arrays in each loops.
{
"expr": "get",
"base": { "expr": "var", "name": "item" },
"path": "title"
}| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "get" | Yes | - | Expression type identifier. |
| base | Expression | Yes | - | Base expression (typically a variable or state). |
| path | string | Yes | - | Dot-separated path to the property. |
Path Access
The path supports dot notation for nested properties:
// Access item.user.profile.name
{
"expr": "get",
"base": { "expr": "var", "name": "item" },
"path": "user.profile.name"
}Note
If a property in the path doesn't exist, the expression returns undefined. This allows safe access to optional properties.
Get vs Var with Path
Both get and var with path can access nested properties. Use get when the base is a computed expression, and var with path when accessing a simple loop variable.
// Using var with path (simpler for loop variables)
{ "expr": "var", "name": "user", "path": "email" }
// Using get (when base is computed or for clarity)
{
"expr": "get",
"base": { "expr": "var", "name": "user" },
"path": "email"
}Usage in Each Loop
{
"kind": "each",
"items": { "expr": "state", "name": "todos" },
"as": "todo",
"index": "i",
"body": {
"kind": "element",
"tag": "div",
"children": [
{
"kind": "text",
"value": {
"expr": "get",
"base": { "expr": "var", "name": "todo" },
"path": "title"
}
},
{
"kind": "text",
"value": {
"expr": "cond",
"if": {
"expr": "get",
"base": { "expr": "var", "name": "todo" },
"path": "done"
},
"then": { "expr": "lit", "value": " [Completed]" },
"else": { "expr": "lit", "value": " [Pending]" }
}
}
]
}
}Route Expression
Accesses route parameters, query strings, or the current path in routed applications.
{ "expr": "route", "name": "id" }
{ "expr": "route", "name": "search", "source": "query" }
{ "expr": "route", "source": "path" }| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "route" | Yes | - | Expression type identifier. |
| name | string | No | - | Name of the route parameter or query parameter. |
| source | "param" | "query" | "path" | No | "param" | Source of the route value. |
Source Types
| Source | Description | Example URL | Expression |
|---|---|---|---|
param | Dynamic path segment | /posts/123 | { "expr": "route", "name": "id" } |
query | URL query parameter | /search?q=test | { "expr": "route", "name": "q", "source": "query" } |
path | Full current path | /docs/intro | { "expr": "route", "source": "path" } |
Example
{
"route": {
"path": "/blog/[slug]"
},
"view": {
"kind": "element",
"tag": "h1",
"children": [{
"kind": "text",
"value": { "expr": "route", "name": "slug" }
}]
}
}Index Expression
Dynamically accesses array elements or object properties using a computed key.
{
"expr": "index",
"base": { "expr": "state", "name": "items" },
"key": { "expr": "state", "name": "selectedIndex" }
}| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "index" | Yes | - | Expression type identifier. |
| base | Expression | Yes | - | Base expression (array or object). |
| key | Expression | Yes | - | Key expression (number for arrays, string for objects). |
Array Access
{
"expr": "index",
"base": { "expr": "state", "name": "users" },
"key": { "expr": "lit", "value": 0 }
}Object Access with Dynamic Key
{
"expr": "index",
"base": { "expr": "import", "name": "translations" },
"key": { "expr": "state", "name": "currentLanguage" }
}Tip
Use index when the key is dynamic (computed at runtime). Use get when the key is a static string known at compile time.
Import Expression
Accesses data from imported JSON files defined in the imports property.
{ "expr": "import", "name": "config" }
{ "expr": "import", "name": "config", "path": "siteName" }| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "import" | Yes | - | Expression type identifier. |
| name | string | Yes | - | Name of the import (key in the imports object). |
| path | string | No | - | Dot-notation path for nested property access. |
Example
{
"imports": {
"config": "../data/config.json",
"nav": "../data/navigation.json"
},
"view": {
"kind": "element",
"tag": "header",
"children": [{
"kind": "text",
"value": { "expr": "import", "name": "config", "path": "siteName" }
}]
}
}Cookie Expression
Reads a value from cookies. Primarily used in state initial for SSR/SSG-safe persistence (e.g., theme preference).
{ "expr": "cookie", "key": "theme", "default": "dark" }| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "cookie" | Yes | - | Expression type identifier. |
| key | string | Yes | - | Cookie name to read. |
| default | string | Yes | - | Fallback value when cookie is not set. |
Usage in State Initial
Cookie expressions are designed for state initialization, enabling SSR/SSG-safe persistence:
{
"state": {
"theme": {
"type": "string",
"initial": { "expr": "cookie", "key": "theme", "default": "dark" }
}
}
}How It Works
| Environment | Behavior |
|---|---|
| SSR/SSG | Reads cookie from HTTP request headers |
| Client | Reads cookie from document.cookie |
| No cookie | Returns the default value |
Tip
Cookie expressions solve the "theme flash" problem. Since the cookie is read during SSR, the initial HTML already contains the correct theme, preventing a flash of the wrong theme on page load.
Note
When using cookie expressions, the cookie value takes precedence over localStorage. This ensures consistency between SSR and client-side rendering.
Data Expression
Accesses data from build-time data sources (glob, file, or API). Used primarily with @constela/start for SSG.
{ "expr": "data", "name": "post" }
{ "expr": "data", "name": "post", "path": "frontmatter.title" }| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "data" | Yes | - | Expression type identifier. |
| name | string | Yes | - | Name of the data source (key in the data object). |
| path | string | No | - | Dot-notation path for nested property access. |
Example with MDX Data Source
{
"data": {
"docs": {
"type": "glob",
"pattern": "content/docs/*.mdx",
"transform": "mdx"
}
},
"view": {
"kind": "element",
"tag": "article",
"children": [
{
"kind": "element",
"tag": "h1",
"children": [{
"kind": "text",
"value": { "expr": "data", "name": "docs", "path": "frontmatter.title" }
}]
},
{
"kind": "markdown",
"content": { "expr": "data", "name": "docs", "path": "content" }
}
]
}
}Ref Expression
References a DOM element by its ref attribute. Used for JavaScript interop.
{ "expr": "ref", "name": "editorContainer" }| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "ref" | Yes | - | Expression type identifier. |
| name | string | Yes | - | Name of the ref (matches the ref attribute on an element). |
Example
{
"view": {
"kind": "element",
"tag": "div",
"props": {
"ref": { "expr": "lit", "value": "editorContainer" }
}
},
"lifecycle": {
"onMount": "initEditor"
},
"actions": [{
"name": "initEditor",
"steps": [{
"do": "call",
"target": { "expr": "var", "name": "monaco", "path": "editor.create" },
"args": [
{ "expr": "ref", "name": "editorContainer" },
{ "expr": "lit", "value": { "language": "json" } }
]
}]
}]
}Note
The ref expression is primarily used with external JavaScript libraries that need direct DOM access, such as code editors, charts, or maps.
Style Expression
Applies style presets with variants, similar to CVA (Class Variance Authority) or Tailwind Variants.
{
"expr": "style",
"name": "button",
"variants": {
"variant": { "expr": "lit", "value": "primary" },
"size": { "expr": "lit", "value": "lg" }
}
}| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "style" | Yes | - | Expression type identifier. |
| name | string | Yes | - | Name of the style preset defined in the styles object. |
| variants | Record<string, Expression> | No | - | Variant selections to apply. Values can be literal or dynamic expressions. |
Example
{
"styles": {
"button": {
"base": "px-4 py-2 rounded font-medium",
"variants": {
"variant": {
"primary": "bg-blue-500 text-white",
"secondary": "bg-gray-200 text-gray-800"
},
"size": {
"sm": "text-sm",
"md": "text-base",
"lg": "text-lg"
}
},
"defaultVariants": {
"variant": "primary",
"size": "md"
}
}
},
"view": {
"kind": "element",
"tag": "button",
"props": {
"className": {
"expr": "style",
"name": "button",
"variants": {
"variant": { "expr": "lit", "value": "primary" }
}
}
},
"children": [{ "kind": "text", "value": { "expr": "lit", "value": "Click me" } }]
}
}Dynamic Variants
Combine with state for dynamic styling:
{
"state": {
"isActive": { "type": "boolean", "initial": false }
},
"view": {
"props": {
"className": {
"expr": "style",
"name": "button",
"variants": {
"variant": {
"expr": "cond",
"if": { "expr": "state", "name": "isActive" },
"then": { "expr": "lit", "value": "primary" },
"else": { "expr": "lit", "value": "secondary" }
}
}
}
}
}
}Tip
Style expressions are resolved at compile time when all variants are static literals. Dynamic variants are resolved at runtime. See the Style System reference for complete documentation.
Concat Expression
Concatenates multiple expressions into a single string. Each expression is evaluated and converted to a string, then joined together.
{
"expr": "concat",
"items": [
{ "expr": "lit", "value": "Hello, " },
{ "expr": "var", "name": "user", "path": "name" },
{ "expr": "lit", "value": "!" }
]
}| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "concat" | Yes | - | Expression type identifier. |
| items | Expression[] | Yes | - | Array of expressions to concatenate. Each is evaluated and converted to string. |
Dynamic Class Names
A common use case is building dynamic CSS class names:
{
"kind": "element",
"tag": "div",
"props": {
"class": {
"expr": "concat",
"items": [
{ "expr": "lit", "value": "avatar rounded-full " },
{ "expr": "var", "name": "user", "path": "avatarSize" },
{ "expr": "lit", "value": " " },
{ "expr": "var", "name": "user", "path": "avatarColor" }
]
}
}
}Combining with Conditionals
{
"expr": "concat",
"items": [
{ "expr": "lit", "value": "btn " },
{
"expr": "cond",
"if": { "expr": "state", "name": "isActive" },
"then": { "expr": "lit", "value": "btn-active" },
"else": { "expr": "lit", "value": "btn-inactive" }
}
]
}Note
Null and undefined values are converted to empty strings. All other values are converted using JavaScript's String() function.
Validity Expression
Accesses HTML5 Constraint Validation API for form elements. Returns validation state from the browser's built-in validation.
{ "expr": "validity", "ref": "emailInput", "property": "valid" }
{ "expr": "validity", "ref": "emailInput", "property": "message" }| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "validity" | Yes | - | Expression type identifier. |
| ref | string | Yes | - | Name of the ref on the form element to check validity for. |
| property | string | No | "valid" | Validity property to access. Defaults to 'valid'. |
Validity Properties
| Property | Type | Description |
|---|---|---|
valid | boolean | true if all constraints pass |
valueMissing | boolean | true if required field is empty |
typeMismatch | boolean | true if value doesn't match type (email, url, etc.) |
patternMismatch | boolean | true if value doesn't match pattern attribute |
tooLong | boolean | true if value exceeds maxLength |
tooShort | boolean | true if value is under minLength |
rangeUnderflow | boolean | true if number is below min |
rangeOverflow | boolean | true if number exceeds max |
stepMismatch | boolean | true if value doesn't match step |
customError | boolean | true if custom validity was set |
message | string | Browser's localized validation message |
Example: Email Validation
{
"state": {},
"actions": [],
"view": {
"kind": "element",
"tag": "div",
"children": [
{
"kind": "element",
"tag": "input",
"ref": "emailInput",
"props": {
"type": { "expr": "lit", "value": "email" },
"required": { "expr": "lit", "value": true },
"placeholder": { "expr": "lit", "value": "Enter your email" }
}
},
{
"kind": "if",
"condition": {
"expr": "not",
"operand": { "expr": "validity", "ref": "emailInput", "property": "valid" }
},
"then": {
"kind": "element",
"tag": "span",
"props": { "className": { "expr": "lit", "value": "text-red-500 text-sm" } },
"children": [{
"kind": "text",
"value": { "expr": "validity", "ref": "emailInput", "property": "message" }
}]
}
}
]
}
}Example: Password Strength
{
"kind": "element",
"tag": "input",
"ref": "passwordInput",
"props": {
"type": { "expr": "lit", "value": "password" },
"minLength": { "expr": "lit", "value": 8 },
"pattern": { "expr": "lit", "value": ".*[A-Z].*" }
}
},
{
"kind": "if",
"condition": { "expr": "validity", "ref": "passwordInput", "property": "tooShort" },
"then": {
"kind": "text",
"value": { "expr": "lit", "value": "Password must be at least 8 characters" }
}
},
{
"kind": "if",
"condition": { "expr": "validity", "ref": "passwordInput", "property": "patternMismatch" },
"then": {
"kind": "text",
"value": { "expr": "lit", "value": "Password must contain an uppercase letter" }
}
}Tip
The validity expression reads directly from the browser's Constraint Validation API, so all standard HTML5 validation attributes (required, pattern, minLength, maxLength, min, max, type, step) work automatically.
Note
Validity is evaluated lazily on each render. The element must exist in the DOM for validity to be checked. If the ref doesn't exist yet, valid returns true and message returns an empty string.
Call Expression
Calls a method on arrays, strings, Math, or Date objects.
Syntax
{
"expr": "call",
"target": <Expression>,
"method": "methodName",
"args": [<Expression>, ...]
}| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "call" | Yes | - | Expression type identifier. |
| target | Expression | Yes | - | The target object (array, string, or Math/Date). |
| method | string | Yes | - | Method name to call. |
| args | Expression[] | No | - | Arguments to pass to the method. |
Array Methods
| Method | Description |
|---|---|
length | Array length |
at | Element at index (supports negative) |
includes | Check if contains value |
slice | Extract portion |
indexOf | Find index of value |
join | Join elements to string |
filter | Filter with lambda |
map | Transform with lambda |
find | Find first matching |
findIndex | Find index of first matching |
some | Check if any match |
every | Check if all match |
String Methods
| Method | Description |
|---|---|
length | String length |
charAt | Character at index |
substring | Extract substring |
slice | Extract portion |
split | Split to array |
trim | Remove whitespace |
toUpperCase | Convert to uppercase |
toLowerCase | Convert to lowercase |
replace | Replace first match |
includes | Check if contains |
startsWith | Check prefix |
endsWith | Check suffix |
indexOf | Find index |
Math Methods
| Method | Description |
|---|---|
min | Minimum of values |
max | Maximum of values |
round | Round to nearest |
floor | Round down |
ceil | Round up |
abs | Absolute value |
sqrt | Square root |
pow | Power |
random | Random 0-1 |
Date Methods
Static: now, parse
Instance: toISOString, getTime, getFullYear, getMonth, getDate, getHours, getMinutes, getSeconds, getMilliseconds
Examples
// Get array length
{ "expr": "call", "target": { "expr": "state", "name": "items" }, "method": "length" }
// Filter completed todos
{
"expr": "call",
"target": { "expr": "state", "name": "todos" },
"method": "filter",
"args": [{
"expr": "lambda",
"param": "todo",
"body": { "expr": "get", "base": { "expr": "var", "name": "todo" }, "path": "completed" }
}]
}
// Math.max
{
"expr": "call",
"target": { "expr": "var", "name": "Math" },
"method": "max",
"args": [{ "expr": "lit", "value": 10 }, { "expr": "state", "name": "count" }]
}Lambda Expression
Anonymous function for array methods like filter, map, find.
Syntax
{
"expr": "lambda",
"param": "item",
"index": "i",
"body": <Expression>
}| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "lambda" | Yes | - | Expression type identifier. |
| param | string | Yes | - | Parameter name for the current item. |
| index | string | No | - | Optional parameter name for the current index. |
| body | Expression | Yes | - | Expression to evaluate for each item. |
Example
{
"expr": "call",
"target": { "expr": "state", "name": "users" },
"method": "map",
"args": [{
"expr": "lambda",
"param": "user",
"index": "i",
"body": { "expr": "get", "base": { "expr": "var", "name": "user" }, "path": "name" }
}]
}Tip
Lambda expressions are used with array methods like filter, map, find, findIndex, some, and every. The param variable is accessible inside the body expression via var expression.
Array Expression
Constructs an array dynamically from expressions. Useful for building arrays where elements can be variables, function call results, or any other expression types.
Syntax
{
"expr": "array",
"elements": [<Expression>, ...]
}| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| expr | "array" | Yes | - | Expression type identifier. |
| elements | Expression[] | Yes | - | Array of expressions to evaluate and include in the result array. |
Basic Examples
// Empty array
{ "expr": "array", "elements": [] }
// Array of literals
{
"expr": "array",
"elements": [
{ "expr": "lit", "value": 1 },
{ "expr": "lit", "value": 2 },
{ "expr": "lit", "value": 3 }
]
}
// Array with state values
{
"expr": "array",
"elements": [
{ "expr": "state", "name": "config" },
{ "expr": "state", "name": "theme" },
{ "expr": "lit", "value": "default" }
]
}CodeMirror Extensions Pattern
A common use case is building extension arrays for libraries like CodeMirror:
// Equivalent to: [basicSetup, json()]
{
"expr": "array",
"elements": [
{ "expr": "var", "name": "basicSetup" },
{
"expr": "call",
"target": { "expr": "var", "name": "json" },
"method": "apply",
"args": []
}
]
}Nested Arrays
// [[1, 2], [3, 4]]
{
"expr": "array",
"elements": [
{
"expr": "array",
"elements": [
{ "expr": "lit", "value": 1 },
{ "expr": "lit", "value": 2 }
]
},
{
"expr": "array",
"elements": [
{ "expr": "lit", "value": 3 },
{ "expr": "lit", "value": 4 }
]
}
]
}Combining with Conditionals
{
"expr": "array",
"elements": [
{ "expr": "var", "name": "baseConfig" },
{
"expr": "cond",
"if": { "expr": "state", "name": "isDebug" },
"then": { "expr": "var", "name": "debugPlugin" },
"else": { "expr": "lit", "value": null }
}
]
}Tip
Array expressions are evaluated at runtime, so each element can be any expression type including state references, variable references, call results, or nested arrays.
Note
Unlike literal arrays in lit expressions which are static, array expressions allow dynamic construction where elements can depend on runtime state or computed values.