Data Types

Understanding data types in JEXL expressions

JEXL Data Types

JEXL supports all JavaScript data types and provides seamless integration with JavaScript's dynamic typing system. Understanding how JEXL handles different data types is crucial for writing effective expressions.

Primitive Types

String

Strings represent textual data and are enclosed in single or double quotes.

// String literals
"hello world"
'single quotes'
"embedded 'quotes'"
'embedded "quotes"'

// Escape sequences
"line 1\nline 2"     // Newline
"tab\tseparated"     // Tab
"quote: \"hello\""   // Escaped quote
"backslash: \\"      // Escaped backslash

String Operations:

// Concatenation
"hello" + " " + "world"        // "hello world"

// Length
length("hello")                // 5

// Case conversion
"Hello" | uppercase            // "HELLO"
"Hello" | lowercase            // "hello"

// Substring operations
"hello world" | substring(0, 5)    // "hello"
"hello world" | split(" ")         // ["hello", "world"]

Number

Numbers can be integers, decimals, or scientific notation.

// Integer literals
42
-17
0

// Decimal literals
3.14159
-2.5
0.001

// Scientific notation
1.23e5      // 123000
4.56e-3     // 0.00456

// Special values
Infinity
-Infinity

Number Operations:

// Arithmetic
10 + 5      // 15
10 - 3      // 7
10 * 2      // 20
10 / 3      // 3.333...
10 % 3      // 1
2 ^ 3       // 8

// Math functions
abs(-5)         // 5
round(3.7)      // 4
floor(3.7)      // 3
ceil(3.2)       // 4
max([1,2,3])    // 3
min([1,2,3])    // 1

Boolean

Booleans represent logical true/false values.

// Boolean literals
true
false

// Boolean expressions
age >= 18           // true/false
name == "John"      // true/false
!isActive          // negation
active && verified  // logical AND
admin || moderator  // logical OR

Truthiness in JEXL:

  • true → true
  • false → false
  • 0 → false
  • "" (empty string) → false
  • null → false
  • undefined → false
  • Everything else → true

Null

Represents the absence of a value.

// Null literal
null

// Null checks
value == null       // Check if null
value != null       // Check if not null

// Default values
name || "Anonymous"  // Use "Anonymous" if name is null/empty

Complex Types

Array

Arrays are ordered collections of values.

// Array literals
[]                    // Empty array
[1, 2, 3]            // Number array
["a", "b", "c"]      // String array
[true, 1, "mixed"]   // Mixed types
[user.name, user.age] // Expression elements

Array Access:

// Index access
users[0]           // First element
users[-1]          // Last element
users[1].name      // Property of array element

// Dynamic access
users[index]       // Using variable

Array Operations:

// Length
length([1, 2, 3])            // 3

// Transform operations
[1, 2, 3] | map("value * 2")     // [2, 4, 6]
[1, 2, 3, 4] | filter("value > 2")  // [3, 4]
["c", "a", "b"] | sort           // ["a", "b", "c"]

// Aggregation
[1, 2, 3, 4] | sum              // 10
[1, 2, 3, 4] | average          // 2.5
[1, 2, 3, 4] | max              // 4

// Array manipulation
[1, 2] | append(3)              // [1, 2, 3]
[1, 2, 3] | reverse             // [3, 2, 1]
[1, 2, 2, 3] | distinct         // [1, 2, 3]

Object

Objects are collections of key-value pairs.

// Object literals
{}                          // Empty object
{name: "John", age: 30}    // Simple object
{x: 1, y: 2, sum: x + y}  // Computed values
{"key-with-dash": value}   // Quoted keys
{[dynamicKey]: value}      // Computed keys

Object Access:

// Property access
user.name              // Dot notation
user["name"]           // Bracket notation
user[propertyName]     // Dynamic property

// Nested access
user.profile.email
user.settings.theme.dark

Object Operations:

// Object inspection
keys({a: 1, b: 2})          // ["a", "b"]
values({a: 1, b: 2})        // [1, 2]
entries({a: 1, b: 2})       // [["a", 1], ["b", 2]]

// Object merging
merge({a: 1}, {b: 2})       // {a: 1, b: 2}

// Property existence
"name" in user              // true if property exists

Type Conversion

JEXL handles automatic type conversion in many contexts.

String Conversion

// Automatic string conversion
"Score: " + 95              // "Score: 95"
"Items: " + 3               // "Items: 3"

// Explicit conversion
string(42)                  // "42"
string(true)                // "true"
string([1, 2, 3])          // "1,2,3"

Number Conversion

// Automatic number conversion
"10" * 2                   // 20
"3.14" + 1                 // 4.14

// Explicit conversion
number("42")               // 42
number("3.14")             // 3.14
number(true)               // 1
number(false)              // 0

// Parsing integers
parseInteger("42")         // 42
parseInteger("42.7")       // 42
parseInteger("42px")       // 42

Boolean Conversion

// Automatic boolean conversion
!!"hello"                  // true
!0                         // true
!"" (empty string)         // true

// Explicit conversion
boolean(1)                 // true
boolean(0)                 // false
boolean("hello")           // true
boolean("")                // false

Working with JSON

JEXL can parse and generate JSON strings.

// Parse JSON
json('{"name": "John", "age": 30}')  // {name: "John", age: 30}

// Generate JSON (automatic)
{name: "John", age: 30}              // Becomes JSON when serialized

Type Checking

While JEXL is dynamically typed, you can check types when needed.

// Type-specific operations indicate type
length(value)           // Works with strings and arrays
keys(value)             // Works with objects
value + ""              // Convert to string
value * 1               // Convert to number
!!value                 // Convert to boolean

Special Values

Undefined vs Null

// Undefined properties
user.nonexistentProperty    // undefined

// Explicit null
user.optionalField = null   // null

// Both are falsy
!undefined                  // true
!null                       // true

Infinity and NaN

// Infinity
1 / 0                      // Infinity
-1 / 0                     // -Infinity

// Not a Number (NaN)
"hello" * 2                // NaN
sqrt(-1)                   // NaN

Array vs Object Distinction

Understanding when to use arrays vs objects:

Use Arrays When:

  • You have ordered data
  • You need indexed access
  • You want to use array transforms (map, filter, etc.)
scores = [85, 92, 78, 96]
scores | average                    // Calculate average
scores | filter("value > 80")      // Filter high scores

Use Objects When:

  • You have key-value relationships
  • You need named properties
  • You want to group related data
user = {name: "John", age: 30, email: "john@example.com"}
user.name                          // Access by property name
keys(user)                         // Get all property names

Common Type Patterns

Safe Property Access

// Handle missing properties
user.profile?.email || "No email"
user && user.profile && user.profile.email

// Using in operator
"email" in user ? user.email : "No email"

Type-Safe Operations

// Ensure array before using array operations
length(users) > 0 ? users | map("value.name") : []

// Ensure string before string operations
typeof name == "string" ? name | uppercase : name

Default Values

// Provide defaults for missing values
name || "Anonymous"
age || 0
tags || []
settings || {}

Best Practices

1. Be Explicit with Types

// Good - clear intent
string(value) | uppercase

// Less clear - relies on conversion
value + "" | uppercase

2. Handle Missing Data

// Good - safe access
users && users | length > 0 ? users[0].name : "No users"

// Risky - might throw error
users[0].name

3. Use Appropriate Data Structures

// Good - use array for ordered data
scores | sort | reverse

// Good - use object for key-value data
settings.theme.primaryColor

Next: Learn about JEXL Operators and how they work with different data types.

Cookie Notice

We use cookies to enhance your browsing experience.