Skip to main content
Luau is a dialect of Lua with a gradual type system and additional syntax features, primarily used by Roblox.

Feature Flag

To parse Luau syntax, you must enable the luau feature flag in your Cargo.toml:
[dependencies]
full_moon = { version = "2.1", features = ["luau"] }
Note: The luau feature can be used standalone or with other Lua version features.

Type System

TypeInfo

The main enum representing all type annotations in Luau. Location: full_moon::ast::luau::TypeInfo
pub enum TypeInfo {
    Array { braces: ContainedSpan, access: Option<TokenReference>, type_info: Box<TypeInfo> },
    Basic(TokenReference),
    String(TokenReference),  // Singleton string: "hello"
    Boolean(TokenReference), // Singleton boolean: true
    Callback { generics: Option<GenericDeclaration>, parentheses: ContainedSpan, arguments: Punctuated<TypeArgument>, arrow: TokenReference, return_type: Box<TypeInfo> },
    Generic { base: TokenReference, arrows: ContainedSpan, generics: Punctuated<TypeInfo> },
    GenericPack { name: TokenReference, ellipsis: TokenReference },
    Intersection(TypeIntersection),
    Module { module: TokenReference, punctuation: TokenReference, type_info: Box<IndexedTypeInfo> },
    Optional { base: Box<TypeInfo>, question_mark: TokenReference },
    Table { braces: ContainedSpan, fields: Punctuated<TypeField> },
    Typeof { typeof_token: TokenReference, parentheses: ContainedSpan, inner: Box<Expression> },
    Tuple { parentheses: ContainedSpan, types: Punctuated<TypeInfo> },
    Union(TypeUnion),
    Variadic { ellipsis: TokenReference, type_info: Box<TypeInfo> },
    VariadicPack { ellipsis: TokenReference, name: TokenReference },
}

Type Examples

Basic Types

local name: string = "John"
local age: number = 25
local isActive: boolean = true

Array Types

local numbers: { number } = {1, 2, 3}
local names: { string } = {"Alice", "Bob"}

-- With access modifier
local readOnlyArray: { read number } = {1, 2, 3}

Table Types

type Person = {
  name: string,
  age: number,
  email: string?
}

local person: Person = {
  name = "Alice",
  age = 30,
  email = "[email protected]"
}

Union Types

type StringOrNumber = string | number
type Result = "success" | "error" | "pending"

-- Leading pipe syntax
type Color = 
  | "red"
  | "green"
  | "blue"

Intersection Types

type Named = { name: string }
type Aged = { age: number }
type Person = Named & Aged

Optional Types

local value: string? = nil
local count: number? = 42

Function Types

type Callback = (x: number, y: number) -> number
type GenericMap<T, U> = (value: T) -> U

local add: (a: number, b: number) -> number = function(a, b)
  return a + b
end

Generic Types

type Array<T> = { T }
type Map<K, V> = { [K]: V }
type Result<T, E> = { success: true, value: T } | { success: false, error: E }

Type Declarations

TypeDeclaration

pub struct TypeDeclaration {
    pub(crate) type_token: TokenReference,
    pub(crate) base: TokenReference,
    pub(crate) generics: Option<GenericDeclaration>,
    pub(crate) equal_token: TokenReference,
    pub(crate) declare_as: TypeInfo,
}
type UserId = number
type Point = { x: number, y: number }
type Callback<T> = (value: T) -> ()

ExportedTypeDeclaration

export type PublicAPI = {
  init: () -> (),
  process: (data: string) -> boolean
}

TypeFunction

User-defined type functions for advanced type manipulation.
type function Pairs()
  -- Type function implementation
end

Type Specifiers

TypeSpecifier

Adds type annotations to variables and parameters.
local x: number = 5

function greet(name: string): string
  return "Hello, " .. name
end

TypeAssertion

Runtimetype assertions using ::.
local value = getValue() :: string
local count = (data.count) :: number

Luau-Specific Syntax

If Expressions

Ternary-like conditional expressions.
local result = if condition then value1 else value2
local grade = if score >= 90 then "A" elseif score >= 80 then "B" else "C"

String Interpolation

Template strings with embedded expressions.
local name = "World"
local greeting = `Hello, {name}!`
local result = `2 + 2 = {2 + 2}`

Compound Assignment Operators

Luau supports a subset of compound operators. For the full set including bitwise operators, see CfxLua.
x += 1   -- x = x + 1
y -= 2   -- y = y - 2
z *= 3   -- z = z * 3
w /= 4   -- w = w / 4
a ^= 2   -- a = a ^ 2
b //= 2  -- b = b // 2 (floor division)
c %= 5   -- c = c % 5
s ..= "!" -- s = s .. "!"

Function Attributes

Attributes can be applied to function declarations.
@native
function fastCompute(x: number): number
  return x * 2
end

Type Instantiation

Generic type parameters at call sites.
local result = identity<<string>>("hello")
local array = create<<number>>()

Advanced Type Features

Generic Type Packs

type Callback<T...> = (T...) -> ()

Variadic Types

function f(...: string)  -- All varargs must be strings
  -- ...
end

type ReturnMultiple = () -> (string, number, boolean)

Module Types

local MyModule = require(script.MyModule)
local value: MyModule.ExportedType

Index Signatures

type Dictionary = {
  [string]: number
}

type StringArray = {
  [number]: string
}

Singleton Types

type Status = "active" | "inactive"
type Version = 1 | 2 | 3
type Enabled = true

Usage

use full_moon::parse;
use full_moon::ast::luau::{TypeInfo, TypeDeclaration, TypeSpecifier};

let ast = parse(r#"
  type Point = { x: number, y: number }
  
  local function distance(p1: Point, p2: Point): number
    local dx = p2.x - p1.x
    local dy = p2.y - p1.y
    return math.sqrt(dx * dx + dy * dy)
  end
"#)?;

Key Type Structures

TypeField

Fields in table types.
pub struct TypeField {
    pub(crate) access: Option<TokenReference>,
    pub(crate) key: TypeFieldKey,
    pub(crate) colon: TokenReference,
    pub(crate) value: TypeInfo,
}
type Config = {
  read timeout: number,
  retries: number,
  [string]: any  -- Index signature
}

GenericDeclaration

type Box<T> = { value: T }
type Map<K, V> = { [K]: V }
type Callback<T, U = T> = (input: T) -> U  -- With default type

Notes

  • Luau’s type system is gradual - you can mix typed and untyped code
  • Type checking happens at compile-time (in Roblox Studio) but types don’t affect runtime behavior
  • The luau feature can be combined with lua52, lua53, etc., but Luau’s own syntax takes precedence
  • See the Luau RFC repository for detailed specifications

Build docs developers (and LLMs) love