Conditionals
Conditionals work like TypeScript conditionals, except block bodies use ( and ) instead of { and }.
if (condition1) (
// Run code
)
else if (condition2) (
// Run code
)
else (
// Run code
)
The format is:
if (<condition>) (
<statements>
)
else if (<condition>) (
<statements>
)
else (
<statements>
)
else if and else branches are optional. An else branch, when present, must be the final branch.
Conditional bodies always require parenthesized blocks. The language does not support TypeScript-style braceless single-statement bodies.
// ❌ Wrong
if (ready)
start()
Use:
if (ready) (
start()
)
if is statement-only. It does not produce a value and cannot be used as an expression.
Use a ternary for two-arm expression selection. Use matches for multi-arm expression selection.
Condition Types
An if condition must be either:
- a
boolean - a nullable value
- an expression that produces one of those types, such as a comparison or an
ischeck
Unlike TypeScript and JavaScript, conditionals do not use general truthiness. Strings, numbers, arrays, objects, and other non-boolean values are not accepted as conditions merely because they could be interpreted as true or false.
if (count) (
// Invalid: numbers are not coerced to boolean
)
if (count !== 0) (
// Valid
)
The editor may offer an expansion for numeric values in condition position. For example, placing a number in an if condition can be rewritten to an explicit comparison against zero.
if (count) (
// Editor can expand to:
)
if (count !== 0) (
// Explicit numeric condition
)
The same rule applies to strings and collections. They require explicit checks.
if (name !== "") (
console.log(name)
)
if (items.length !== 0) (
console.log(items)
)
Nullable Conditions
Nullable values are allowed directly in condition position. The condition checks whether the condition expression itself is not null.
if (user) (
console.log(user.name)
)
else (
console.log("No user")
)
Inside the truthy branch, the value is narrowed to its non-null type. Inside the else branch, the value is narrowed to null when the original type permits that conclusion.
user is User or null
if (user) (
// user is User here
console.log(user.name)
)
else (
// user is null here
)
A non-nullable value is not allowed directly in condition position just because it contains nullable fields.
profile is Profile
if (profile) (
// Invalid: profile itself is not nullable
)
if (profile.photo) (
// Valid when profile.photo is nullable
)
Nullable values keep their type when assigned to a local. The local can then be checked directly.
photo = profile.photo
if (photo) (
// photo is the non-null photo type here
)
Nullable booleans follow the same rule: false is still a boolean value, not null.
enabled is boolean or null
if (enabled) (
// enabled is boolean here, and its value is true
)
else (
// enabled is false or null here
)
Use an explicit comparison when the distinction matters.
if (enabled !== null) (
// enabled is boolean here
)
Branch Evaluation
Branches are tested from top to bottom. The first branch whose condition passes is executed, and the remaining branches are skipped.
if (status === "ready") (
start()
)
else if (status === "waiting") (
queue()
)
else (
cancel()
)
This has the same control-flow behavior as a TypeScript if / else if / else chain.