Skip to main content

Types

Jade has nine runtime value types.

TypeDescriptionStatus
int64-bit signed integer (i64)Implemented
float64-bit floating point (f64)Implemented
boolBoolean true or falseImplemented
fnFirst-class function valueImplemented
structUser-defined record type with named fieldsImplemented
strUTF-8 string with indexing and concatenationImplemented
arrayHeterogeneous mutable array with index accessImplemented
dictString-keyed mutable hash mapImplemented
nilAbsence of valueImplemented

Type Coercion Rules

Jade does not implicitly coerce types except in specific arithmetic and comparison contexts:

RuleExampleResult
Arithmetic: int op float → float1 + 0.51.5 (float)
Ordering: int < float allowed1 < 2.5true
Strict equality: no cross-type coercion1 == 1.0TypeError
Bool ordering: false = 0, true = 1false < truetrue
Bitwise: integer operands only1.0 & 2TypeError
Logical: bool operands only1 && trueTypeError
note

Arithmetic promotion converts an int to float when the other operand is a float. Equality never promotes — comparing 1 to 1.0 is always a TypeError.

Nil

nil is Jade's single "absence of value" type. A function that reaches the end of its body without returning, a bare return, and most mutating built-ins (arr.push(x), fs.write(...)) all evaluate to nil.

Three spellings

nil, None, and null are interchangeable spellings of the same value. They all evaluate to the one nil, compare equal to each other, and can be used anywhere a literal is expected (including default parameter values and type annotations).

let a = nil
let b = None
let c = null

print(a == b) // true
print(b == c) // true

fn greet(name = null) { // default parameter
return name
}
print(greet()) // nil
note

The three spellings are aliases, not distinct types — there is no separate null type. JSON null also decodes to this same nil.

Dict

A dict is a mutable, string-keyed hash map. Keys are strings; values can be any Jade type. Dicts are created with curly-brace literal syntax and accessed with square-bracket indexing.

Creating a dict

let d = {"name": "jade", "version": 1}
let empty = {}

Bare identifiers are also accepted as keys — the identifier's string value becomes the key:

let key = "hello"
let greet = {key: "world"}
print(greet["hello"]) // world

Reading and writing values

print(d["name"]) // jade

d["version"] = 2 // update existing key
d["stable"] = true // add new key

Length

print(len(d)) // number of key-value pairs

Value semantics

Assigning a dict to a new variable copies it. Mutations to the copy do not affect the original:

let d2 = d
d2["name"] = "copy"
print(d["name"]) // jade (unchanged)
print(d2["name"]) // copy

Nested dicts

let outer = {"inner": {"x": 42}}
let inner = outer["inner"]
print(inner["x"]) // 42
note

Dict keys are always strings. Accessing a key that does not exist produces a runtime error.