Skip to content

Types Reference

TypeDescriptionExample
stringText"hello"
numberInteger or float42, 3.14
booleanBooleantrue, false
TypeDescription
Result<T, E>Success (Ok(T)) or failure (Err(E))
Option<T>Present (Some(T)) or absent (None)
Array<T>Ordered collection
Promise<T>Async value
Brand<T, Tag>Compile-time distinct type

Named product types with fields:

type User {
name: string,
email: string,
age: number,
}

Compiles to TypeScript type:

type User = {
name: string;
email: string;
age: number;
};

Include fields from other record types using ... spread:

type BaseProps {
className: string,
disabled: boolean,
}
type ButtonProps {
...BaseProps,
onClick: fn() -> (),
label: string,
}

Compiles to TypeScript intersection:

type BaseProps = { className: string; disabled: boolean };
type ButtonProps = BaseProps & { onClick: () => void; label: string };

Multiple spreads are allowed. Field name conflicts are compile errors.

Tagged discriminated unions:

type Shape {
| Circle { radius: number }
| Rectangle { width: number, height: number }
| Point
}

Compiles to TypeScript discriminated union:

type Shape =
| { _tag: "Circle"; radius: number }
| { _tag: "Rectangle"; width: number; height: number }
| { _tag: "Point" };

String literal unions for npm interop:

type HttpMethod = "GET" | "POST" | "PUT" | "DELETE"

Compiles to the same TypeScript type (pass-through):

type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";

Match arms use string comparisons instead of tag checks:

match method {
"GET" -> "fetching",
"POST" -> "creating",
"PUT" -> "updating",
"DELETE" -> "removing",
}

Exhaustiveness is checked — missing a variant is a compile error.

Types that are distinct at compile time but erase to their base type at runtime:

type UserId = Brand<string, "UserId">
type PostId = Brand<string, "PostId">

UserId and PostId are both string at runtime, but the compiler prevents mixing them up.

Types where internals are hidden from other modules:

opaque type Email = string

Only code in the module that defines Email can construct or destructure it. Other modules see it as an opaque blob.

// Named
User
string
// Generic
Array<number>
Result<User, Error>
Option<string>
// Function
fn(number, number) -> number
// Record (inline)
{ name: string, age: number }
// Array
Array<T>
// Tuple
[string, number]
TypeWhy BannedAlternative
anyDisables all type checkingunknown + pattern matching
nullNullable reference bugsOption<T> with None
undefinedSame problem as nullOption<T> with None
enumCompiles to runtime objectsUnion types
interfaceRedundant with typetype
voidImplicit undefinedExplicit return types