Luauチートシート
型チェックモード
ファイル1行目のコメントで、Luauがどこまで厳しく型を見るかが決まります。
| モード | 構文 |
|---|---|
| 型チェックなし | --!nocheck |
| 既定: 注釈した箇所だけ検査 | --!nonstrict |
| strict: 推論して全体を検査 | --!strict |
| ファイルを実行 | luau main.luau |
| 実行せずに型チェック | luau-analyze main.luau |
| lint警告を1つ無効化 | --!nolint UnknownGlobal |
基本の型
プリミティブ型と変数への注釈の付け方。
| 操作 | 構文 |
|---|---|
| 数値 | local age: number = 25 |
| 文字列 | local name: string = "Ada" |
| 真偽値 | local ok: boolean = true |
| オプショナル(nilの可能性) | local nick: string? = nil |
| any(検査対象外) | local x: any = f() |
| unknown(より安全なany) | local x: unknown = f() |
| never(常に例外を投げる) | function fail(): never error("boom") end |
| nil | local n: nil = nil |
| コルーチン / buffer | local co: thread, local b: buffer |
| 推論される(注釈不要) | local hp = 100 -- number |
型付きテーブル: 配列とマップ
実体はLuaのテーブルのまま。型は中身が何かを示すだけです。
| 操作 | 構文 |
|---|---|
| 数値の配列 | local xs: {number} = {1, 2, 3} |
| 文字列の配列 | local names: {string} = {} |
| マップ(文字列キー) | local ages: {[string]: number} = {} |
| マップ(任意のキー型) | local seen: {[Player]: boolean} = {} |
| ネストした配列 | local grid: {{number}} = {} |
| 構造の配列 | local items: {{id: number}} = {} |
| 読み取り専用の配列 | local t = table.freeze({1, 2, 3}) |
| 反復(汎用イテレーション、Luau固有) | for i, v in xs do print(i, v) end |
| キーと値を反復 | for k, v in pairs(ages) do end |
関数
引数と戻り値に注釈を付けます。-> ()は「戻り値なし」です。
| 操作 | 構文 |
|---|---|
| 引数と戻り値に型 | function add(a: number, b: number): number |
| 戻り値なし | function log(msg: string): () end |
| 複数の戻り値 | function split(s: string): (string, string) |
| オプショナル引数 | function greet(name: string?) end |
| 既定値 | function greet(name: string?) name = name or "friend" end |
| 可変長引数 | function sum(...: number): number end |
| 無名関数 | local f = function(x: number): number return x * 2 end |
| 関数型 | type Adder = (number, number) -> number |
| コールバック引数 | function each(f: (number) -> ()) end |
型エイリアス・ユニオン・リテラル
型に一度名前を付けて、どこでも使い回します。
| 操作 | 構文 |
|---|---|
| プリミティブのエイリアス | type Health = number |
| ユニオン型 | type Id = number | string |
| オプショナル = nilとのユニオン | type Maybe = string | nil -- same as string? |
| リテラル(シングルトン)型 | type Dir = "up" | "down" |
| インターセクション型 | type Both = Named & Aged |
| ジェネリックなエイリアス | type List<T> = {T} |
| モジュールからエクスポート | export type Point = { x: number, y: number } |
| 既存の値の型 | type Config = typeof(config) |
| テーブル型のキー一覧 | type K = keyof<Point> |
テーブルの形とメソッド
オブジェクトの記述と、コロン呼び出しについてくるself。
| 操作 | 構文 |
|---|---|
| インラインの形 | local p: { x: number, y: number } = { x = 0, y = 0 } |
| 名前付きの形 | type Point = { x: number, y: number } |
| オプショナルなプロパティ | type User = { name: string, age: number? } |
| 形 + インデクサ | type Bag = { count: number, [string]: any } |
| 形を拡張 | type Admin = User & { level: number } |
| メソッド(コロン記法) | function Point.move(self: Point, dx: number) end |
| 型の中のメソッド | type Point = { move: (self: Point, dx: number) -> () } |
| コンストラクタのパターン | function Point.new(x: number): Point end |
| 凍結した定数(enum風) | local Color = table.freeze({ Red = 1, Blue = 2 }) |
ジェネリクス
多くの値の型に対して使える1つの関数や型。
| 操作 | 構文 |
|---|---|
| ジェネリック関数 | function id<T>(x: T): T return x end |
| 型引数2つ | function pair<A, B>(a: A, b: B): (A, B) end |
| 配列に対するジェネリック | function first<T>(xs: {T}): T? return xs[1] end |
| ジェネリック型エイリアス | type Stack<T> = { items: {T} } |
| エイリアスを具体化 | local s: Stack<string> = { items = {} } |
| ジェネリックなmap関数 | function map<T, U>(xs: {T}, f: (T) -> U): {U} end |
| ジェネリックパック(可変長) | function call<T...>(f: () -> T...): T... end |
絞り込み・アサーション・型ガード
「この値はこの型だ」と型チェッカーに納得させる方法。
| 操作 | 構文 |
|---|---|
| 型アサーション(キャスト) | local n = value :: number |
| any経由のキャスト | local n = (value :: any) :: number |
| typeofで絞り込む | if typeof(x) == "string" then -- x is string end |
| オプショナルを絞り込む | if name then print(#name) end |
| nilなら早期リターン | if not name then return end |
| リテラルユニオンを絞り込む | if dir == "up" then end |
| 実行時チェック | assert(typeof(id) == "number", "id must be a number") |
| nilでないことを保証して使う | local item = assert(find(id), "missing item") |
Luaにない演算子と構文
日常的に効く追加機能 - Luauのコードが素のLuaに見えなくなる部分です。
| 操作 | 構文 |
|---|---|
| 加算して代入 | hp += 10 |
| 減算 / 乗算 / 除算 | hp -= 5, dmg *= 2, dmg /= 2 |
| 切り捨て除算して代入 | n //= 2 |
| 剰余 / べき乗して代入 | n %= 3, n ^= 2 |
| 連結して代入 | msg ..= "!" |
| 切り捨て除算 | local half = 7 // 2 -- 3 |
| 文字列補間 | Hello, {name}! You have {n} items.(バッククォートで囲む) |
| 式を埋め込む | Total: {price * qty}(バッククォートで囲む) |
| ループを継続 | for _, v in xs do if v < 0 then continue end end |
| if-then-else式 | local label = if hp > 0 then "alive" else "dead" |
| else-ifを連ねた式 | local t = if n > 0 then "pos" elseif n < 0 then "neg" else "zero" |
| 2進リテラル / 桁区切り | 0b1010, 1_000_000 |
ライブラリの追加とLuaとの違い
Luauが標準ライブラリに追加した関数と、Luaから削除された機能。
| 項目 | 詳細 |
|---|---|
| 配列から値を探す | table.find(xs, 42) -- インデックスまたはnil |
| 浅いコピー | local copy = table.clone(t) |
| 不変にする / 判定する | table.freeze(t), table.isfrozen(t) |
| 配列を事前確保 | table.create(10, 0) |
| clamp / round / sign | math.clamp(x, 0, 1), math.round(x), math.sign(x) |
| ビット演算 | bit32.band(a, b), bit32.lshift(a, 1) |
| サンドボックス化のため削除 | io, package, loadstring, loadfile, dofile |
| 非推奨だが存在する | getfenv、setfenv(最適化が無効になる) |
| Luauには無い | goto/ラベル(LuauはLua 5.1がベース) |
| Coddyでの標準入力 | io.read()はここでは使える - CoddyがLuauの上で復活させている |
| ファイル拡張子 | main.luau(.luaでも動く) |
| Roblox限定(Luau本体ではない) | game, workspace, Instance.new, task.wait |
LuauはLua 5.1に漸進的な型システムを加えた言語で、Robloxが開発してオープンソース化しました。このチートシートは素のLuaには*ない*部分を扱います: 型注釈、型付きテーブル、ユニオン型とリテラル型、ジェネリクス、型アサーション、そしてLuauが追加した構文糖(+=、文字列補間、continue、if-then-else式)。テーブル、メタテーブル、コルーチン、文字列ライブラリなど両言語で共通の部分はLuaチートシートを並べて開いてください。
ここにあるものはすべて標準のLuauで、luau CLIで実行でき、luau-analyzeで型チェックできます。必要な行をコピーするか、Luauプレイグラウンドでそのまま実行してみてください - インストールは不要です。型システムを一から学ぶなら、Coddyの無料インタラクティブLuau講座がレッスンごとに積み上げます。
Luauチートシートのよくある質問
このLuauチートシートは無料ですか?
Luauに+=演算子はありますか?
+=、-=、*=、/=、//=、%=、^=、そして文字列連結の..=。つまりhp += 10は正しいLuau(かつ正しいRobloxのコード)で、Lua 5.1ではhp = hp + 10と書く必要があります。なお、Luauに++や--はありません。LuaとLuauの違いは何ですか?
continue、if-then-else式、切り捨て除算//、汎用イテレーション(for i, v in t do)、table.find・table.clone・table.freezeなどの関数が加わります。サンドボックス化のためloadstring、loadfile、dofileとio・packageライブラリは削除され、5.1がベースなのでgotoはありません。通常のLuaコードはほとんどそのままLuauとして動きます。Luauで型チェックを有効にする方法は?
--!strictはすべてを検査して積極的に推論し、--!nonstrict(既定)は注釈した箇所だけを検査し、--!nocheckは検査を無効にします。エディタ以外では、実行せずに型を見るならluau-analyze main.luau、実行するならluau main.luauです。TypeScriptのようにinterfaceと書きますか?
interfaceキーワードはありません。オブジェクトの形はテーブル型として書き、typeで名前を付けます: type User = { name: string, age: number? }。extendsではなく&で形を組み合わせ、他のモジュールに公開するにはexport typeを使います。このチートシートはRobloxのスクリプティングと同じですか?
game、workspace、Instance.new、サービス、イベント)です。これは言語の上に載ったライブラリで、Luauではなく Robloxが文書化しています。これらのLuauコードはどこで実行できますか?
luauインタプリタを標準入力対応で実行するので、このページの行をそのまま貼り付けて実行できます。体系的に練習するなら、インタラクティブLuau講座が同じ内容を演習・プロジェクト・修了証つきで扱います。