Luau syntax features
Luau extends Lua with type annotations, generalized iteration, string interpolation, and several smaller features. luau2ts handles each one.
Type annotations
local x: number = 1
local function f(a: string, b: number): boolean
return #a > b
end
const x: number = 1;
function f(a: string, b: number): boolean {
return lualen(a) > b;
}
Compound types ({[string]: number}, (string, number) -> boolean, T?) translate to their TypeScript equivalents.
Type aliases
type Vec3 = { x: number, y: number, z: number }
type Result<T> = { ok: true, value: T } | { ok: false, error: string }
type Vec3 = { x: number; y: number; z: number };
type Result<T> = { ok: true; value: T } | { ok: false; error: string };
Generic type parameters, intersection types (&), and union types (|) all work.
Type assertions
local x = (something :: number)
const x = (something as number);
--!strict / --!nonstrict
These directives at the top of a Luau file are dropped from the output, they're Luau-side type-checker hints with no TypeScript equivalent. The TS-side strict setting in tsconfig.json is what controls strict typing post-compilation.
String interpolation
local greeting = `Hello, {name}!`
const greeting = `Hello, ${name}!`;
Luau backticks become JS template literals. {expr} substitutions become ${expr}.
Generalized iteration
for k, v in t do end
When t is statically typable as an array, lowers to a fast indexed loop. Otherwise it goes through genericIter(t) which lifts the value into the standard iter / state / control triple.
Continue
for i = 1, 10 do
if i % 2 == 0 then continue end
print(i)
end
for (let i = 1; i <= 10; i++) {
if (i % 2 === 0) continue;
print(i);
}
Compound assignment
counter += 1
buffer ..= "more"
counter += 1;
buffer = concat(buffer, "more");
The ..= form expands because TypeScript doesn't have a string-concat compound operator.
What's not supported
goto/::label::, Luau has no goto, but some hand-written Lua 5.1 code might. Not yet supported.- Lua-style escape characters that Luau itself rejects (
\G,\Ketc. in old Roblox scripts), the parser normalises these to bare characters during a pre-pass, so they compile without error.