Skip to content

Unify type definition syntax: use {} for all type fields #340

@milkyskies

Description

@milkyskies

Summary

Unify type definition syntax so both records and unions use { } for fields/variants. Construction stays as ( ). Support inline nested unions.

Proposed syntax

Records

// No = needed, { } directly after name
type User {
    name: string,
    age: number,
}

// Record composition
type ButtonProps {
    ...BaseProps,
    onClick: fn() -> (),
    label: string,
}

Unions

// { } with | for variants
type Shape {
    | Circle { radius: number }
    | Rectangle { width: number, height: number }
    | Point
}

Inline nested unions

type AppError {
    | Network {
        | Timeout { ms: number }
        | DnsFailure { host: string }
    }
    | Payment {
        | CardDeclined { reason: string }
        | InsufficientFunds
    }
    | NotFound
    | Auth { message: string }
}

Same pattern at every nesting level: `{ | ... }` is a union, `{ name: type, ... }` is fields.

Newtypes

type OrderId { number }

Aliases and string literal unions (unchanged, still use =)

type Name = string
type Method = "GET" | "POST" | "PUT" | "DELETE"

Parser disambiguation

Peek at first token inside `{ }`:

  • `|` → union (variants)
  • lowercase `name:` → record (fields)
  • bare type name → newtype wrapper

Construction unchanged

const u = User(name: "Alice", age: 30)
const c = Circle(radius: 5)
const id = OrderId(42)

// Matching nested unions — peel off layers
match error {
    Network(Timeout(ms)) -> \`Timed out after \${ms}ms\`,
    Network(DnsFailure(host)) -> \`DNS failed: \${host}\`,
    Payment(CardDeclined(reason)) -> \`Card declined: \${reason}\`,
    Payment(InsufficientFunds) -> "insufficient funds",
    Network(_) -> "network issue",
    NotFound -> "not found",
    Auth(message) -> message,
}

One-line parsing

Works because `{ }` delimit groups unambiguously:

type AppError { | Network { | Timeout { ms: number } | DnsFailure { host: string } } | NotFound }

Current syntax (for reference)

// Record — uses = { }
type User = {
    name: string,
    age: number,
}

// Union — uses = |
type Shape =
    | Circle(radius: number)
    | Rectangle(width: number, height: number)
    | Point

Scope

  • Parser: type definition syntax for records and union variants
  • Codegen: adjust type emission
  • Checker: update type definition handling
  • Support inline nested union definitions (compiler generates intermediate types)
  • All .fl files, test fixtures, example apps
  • Docs (design.md, llms.txt, site)
  • Syntax highlighting (tree-sitter, TextMate)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions