Menu
Coddy logo textTech

Шпаргалка по 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
Nillocal 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
Необязательный = объединение с niltype 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 = {} }
Обобщённая функция mapfunction map<T, U>(xs: {T}, f: (T) -> U): {U} end
Обобщённый пакет (variadic)function call<T...>(f: () -> T...): T... end

Уточнение, приведение и проверки

Как убедить проверяльщик типов, что значение именно такое, как вы знаете.

ОперацияСинтаксис
Приведение типа (cast)local n = value :: number
Приведение через anylocal n = (value :: any) :: number
Уточнение через typeofif typeof(x) == "string" then -- x is string end
Уточнить необязательныйif name then print(#name) end
Ранний выход при nilif 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-elselocal 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 / signmath.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 (отключают оптимизации)
Отсутствует в Luaugoto и метки (Luau основан на Lua 5.1)
Чтение stdin на Coddyio.read() здесь работает - Coddy возвращает его поверх Luau
Расширение файлаmain.luau (.lua тоже работает)
Только Roblox, не базовый Luaugame, 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 оператор +=?
Да. В отличие от обычного Lua, Luau поддерживает составное присваивание: +=, -=, *=, /=, //=, %=, ^= и ..= для склейки строк. То есть hp += 10 - корректный Luau (и корректный код Roblox), тогда как в Lua 5.1 нужно писать hp = hp + 10. Обратите внимание: ++ и -- в Luau нет.
Чем Lua отличается от Luau?
Luau - надмножество Lua 5.1 с постепенной системой типов. Кроме типов он добавляет интерполяцию строк через обратные кавычки, операторы составного присваивания, 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?
Всё здесь - базовый Luau, то есть язык, поэтому подходит и для скриптов Roblox, и для автономного Luau. Чего здесь *нет*, так это API движка Roblox (game, workspace, Instance.new, сервисы, события): это библиотека над языком, и её документирует Roblox, а не Luau.
Где запустить эти примеры на Luau?
В песочнице Luau - она запускает настоящий интерпретатор luau в браузере, с поддержкой stdin, так что можно вставить любую строку с этой страницы и нажать «Запустить». Для системной практики интерактивный курс Luau разбирает тот же материал с упражнениями, проектами и сертификатом.
Coddy programming languages illustration

Изучайте Luau с Coddy

НАЧАТЬ