Шпаргалка по Luau
Режимы проверки типов
Комментарий в первой строке файла задаёт строгость проверки.
| Режим | Синтаксис |
|---|---|
| Без проверки типов | --!nocheck |
| По умолчанию: проверяет размеченное | --!nonstrict |
| Строгий: выводит и проверяет всё | --!strict |
| Запустить файл | luau main.luau |
| Проверить типы без запуска | luau-analyze main.luau |
| Отключить одно предупреждение линтера | --!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 |
| Корутина / буфер | 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 }) |
Дженерики
Одна функция или тип, работающие со многими типами значений.
| Операция | Синтаксис |
|---|---|
| Обобщённая функция | function id<T>(x: T): T return x end |
| Два параметра типа | 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 |
| Обобщённый пакет (variadic) | function call<T...>(f: () -> T...): T... end |
Уточнение, приведение и проверки
Как убедить проверяльщик типов, что значение именно такое, как вы знаете.
| Операция | Синтаксис |
|---|---|
| Приведение типа (cast) | 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" |
| Двоичные литералы и разделители | 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) |
| Чтение stdin на 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: запускается через CLI luau и проверяется через luau-analyze. Копируйте нужное или попробуйте вживую в песочнице Luau - ставить ничего не нужно. Только начинаете с типами? Бесплатный интерактивный курс Luau от Coddy выстраивает их урок за уроком.
Вопросы о шпаргалке по 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, а goto нет, потому что основа - 5.1. Обычный код на Lua чаще всего работает как Luau без изменений.Как включить проверку типов в Luau?
--!strict проверяет всё и активно выводит типы, --!nonstrict (по умолчанию) проверяет только размеченное, --!nocheck отключает проверку. Вне редактора выполните luau-analyze main.luau, чтобы проверить типы без запуска, и luau main.luau, чтобы запустить.Пишут ли в Luau interface, как в TypeScript?
interface в Luau нет. Формы объектов записываются как табличные типы и получают имя через type: type User = { name: string, age: number? }. Объединяйте формы через & вместо extends, а export type открывает тип другим модулям.Эта шпаргалка - то же, что скриптинг в Roblox?
game, workspace, Instance.new, сервисы, события): это библиотека над языком, и её документирует Roblox, а не Luau.Где запустить эти примеры на Luau?
luau в браузере, с поддержкой stdin, так что можно вставить любую строку с этой страницы и нажать «Запустить». Для системной практики интерактивный курс Luau разбирает тот же материал с упражнениями, проектами и сертификатом.