Language Reference

Language Reference

typeDiagram has three constructs: type (records), union (tagged sum types), and alias (newtypes). That's it.

Records (type)

A record has a name, optional generic parameters, and named fields with types.

type User {
  id:      UUID
  name:    String
  email:   Option<Email>
  roles:   List<Role>
  address: Address
}
 

Fields are separated by newlines or commas. Trailing commas are allowed.

Generics

type Pair<A, B> {
  first:  A
  second: B
}

type Box<T> {
  value: T
}
 

Unions (union)

A union represents "one of" — a tagged sum type. Each variant can be bare (no payload) or carry fields.

union Shape {
  Circle    { radius: Float }
  Rectangle { width: Float, height: Float }
  Triangle  { a: Float, b: Float, c: Float }
  Point
}
 

Unions render visually distinct from records: dashed dividers between variants and a | pipe prefix on each variant row.

Generic unions

union Option<T> {
  Some { value: T }
  None
}

union Result<T, E> {
  Ok  { value: T }
  Err { error: E }
}
 

Aliases (alias)

An alias creates a named synonym for another type.

alias Email = String
alias UserId = UUID
alias Callback = Option<String>
 

Built-in types

These primitive types are always available (no declaration needed):

Type Description
Bool Boolean
Int Integer
Float Floating point
String Text
Bytes Binary data
Unit No value (void)

Container types

These are conventionally used but not built-in — they render as external references:

Type Description
List<T> Ordered collection
Map<K, V> Key-value mapping
Option<T> Optional value (declare as a union to get diagram edges)

Comments

Line comments start with #:

# This is a comment
type User {
  name: String  # inline comment
}
 

File header

The optional typeDiagram keyword at the top of a file is a header marker. It's not required.

typeDiagram

type User { ... }
 

Edges (automatic)

Edges are drawn automatically when a field or variant references another type declared in the same diagram:

References to undeclared types (like UUID, String) render as inline text only — no dangling edges.

Grammar (formal)

Diagram     = ("typeDiagram")? Declaration*
Declaration = Record | Union | Alias
Record      = "type" Name Generics? "{" Field* "}"
Union       = "union" Name Generics? "{" Variant* "}"
Alias       = "alias" Name Generics? "=" TypeRef
Field       = Name ":" TypeRef
Variant     = Name ("{" Field* "}")?
TypeRef     = Name ("<" TypeRef ("," TypeRef)* ">")?
Generics    = "<" Name ("," Name)* ">"
Name        = [A-Za-z_][A-Za-z0-9_]*
 

The grammar is LL(1) with ~6 productions. Newlines and commas both work as separators inside { } blocks.