Chuleta de Luau
Modos de verificación de tipos
Un comentario en la primera línea del archivo decide con qué rigor comprueba Luau.
| Modo | Sintaxis |
|---|---|
| Sin verificación de tipos | --!nocheck |
| Por defecto: comprueba lo anotado | --!nonstrict |
| Estricto: infiere y comprueba todo | --!strict |
| Ejecutar un archivo | luau main.luau |
| Verificar tipos sin ejecutar | luau-analyze main.luau |
| Desactivar un aviso del linter | --!nolint UnknownGlobal |
Tipos básicos
Los tipos primitivos y cómo anotar una variable.
| Operación | Sintaxis |
|---|---|
| Número | local age: number = 25 |
| Cadena | local name: string = "Ada" |
| Booleano | local ok: boolean = true |
| Opcional (puede ser nil) | local nick: string? = nil |
| Any (sin comprobación) | local x: any = f() |
| Unknown (any más seguro) | local x: unknown = f() |
| Never (siempre lanza error) | function fail(): never error("boom") end |
| Nil | local n: nil = nil |
| Corrutina / buffer | local co: thread, local b: buffer |
| Inferido: sin anotación | local hp = 100 -- number |
Tablas tipadas: arrays y mapas
Siguen siendo tablas de Lua; el tipo dice qué contienen.
| Operación | Sintaxis |
|---|---|
| Array de números | local xs: {number} = {1, 2, 3} |
| Array de cadenas | local names: {string} = {} |
| Mapa (claves de cadena) | local ages: {[string]: number} = {} |
| Mapa (cualquier tipo de clave) | local seen: {[Player]: boolean} = {} |
| Array anidado | local grid: {{number}} = {} |
| Array de formas | local items: {{id: number}} = {} |
| Array de solo lectura | local t = table.freeze({1, 2, 3}) |
| Iterar (generalizado, solo Luau) | for i, v in xs do print(i, v) end |
| Iterar claves y valores | for k, v in pairs(ages) do end |
Funciones
Anota los parámetros y el tipo de retorno; -> () significa que no devuelve nada.
| Operación | Sintaxis |
|---|---|
| Parámetros y retorno tipados | function add(a: number, b: number): number |
| No devuelve nada | function log(msg: string): () end |
| Retornos múltiples | function split(s: string): (string, string) |
| Parámetro opcional | function greet(name: string?) end |
| Valor por defecto | function greet(name: string?) name = name or "friend" end |
| Variádica | function sum(...: number): number end |
| Función anónima | local f = function(x: number): number return x * 2 end |
| Tipo de función | type Adder = (number, number) -> number |
| Parámetro de callback | function each(f: (number) -> ()) end |
Alias de tipo, uniones y literales
Nombra un tipo una vez y reutilízalo en todas partes.
| Operación | Sintaxis |
|---|---|
| Alias de un primitivo | type Health = number |
| Unión | type Id = number | string |
| Opcional = unión con nil | type Maybe = string | nil -- same as string? |
| Tipo literal (singleton) | type Dir = "up" | "down" |
| Intersección | type Both = Named & Aged |
| Alias genérico | type List<T> = {T} |
| Exportar desde un módulo | export type Point = { x: number, y: number } |
| Tipo de un valor existente | type Config = typeof(config) |
| Claves de un tipo de tabla | type K = keyof<Point> |
Formas de tabla y métodos
Describir objetos, y el self que llega con las llamadas con dos puntos.
| Operación | Sintaxis |
|---|---|
| Forma en línea | local p: { x: number, y: number } = { x = 0, y = 0 } |
| Forma con nombre | type Point = { x: number, y: number } |
| Propiedad opcional | type User = { name: string, age: number? } |
| Forma + indexador | type Bag = { count: number, [string]: any } |
| Extender una forma | type Admin = User & { level: number } |
| Método (atajo con dos puntos) | function Point.move(self: Point, dx: number) end |
| Método en un tipo | type Point = { move: (self: Point, dx: number) -> () } |
| Patrón de constructor | function Point.new(x: number): Point end |
| Constantes congeladas (tipo enum) | local Color = table.freeze({ Red = 1, Blue = 2 }) |
Genéricos
Una función o un tipo que sirve para muchos tipos de valor.
| Operación | Sintaxis |
|---|---|
| Función genérica | function id<T>(x: T): T return x end |
| Dos parámetros de tipo | function pair<A, B>(a: A, b: B): (A, B) end |
| Genérica sobre un array | function first<T>(xs: {T}): T? return xs[1] end |
| Alias de tipo genérico | type Stack<T> = { items: {T} } |
| Instanciar un alias | local s: Stack<string> = { items = {} } |
| Función map genérica | function map<T, U>(xs: {T}, f: (T) -> U): {U} end |
| Paquete genérico (variádico) | function call<T...>(f: () -> T...): T... end |
Estrechamiento, aserciones y guards
Convencer al verificador de que un valor es lo que tú ya sabes.
| Operación | Sintaxis |
|---|---|
| Aserción de tipo (cast) | local n = value :: number |
| Aserción pasando por any | local n = (value :: any) :: number |
| Estrechar con typeof | if typeof(x) == "string" then -- x es string end |
| Estrechar un opcional | if name then print(#name) end |
| Retorno temprano si es nil | if not name then return end |
| Estrechar una unión literal | if dir == "up" then end |
| Comprobación en ejecución | assert(typeof(id) == "number", "id must be a number") |
| Afirmar que no es nil y usarlo | local item = assert(find(id), "missing item") |
Operadores y sintaxis que Lua no tiene
Las mejoras del día a día: aquí es donde el código Luau deja de parecer Lua.
| Operación | Sintaxis |
|---|---|
| Sumar y asignar | hp += 10 |
| Restar / multiplicar / dividir | hp -= 5, dmg *= 2, dmg /= 2 |
| División entera y asignación | n //= 2 |
| Módulo / potencia y asignación | n %= 3, n ^= 2 |
| Concatenar y asignar | msg ..= "!" |
| División entera | local half = 7 // 2 -- 3 |
| Interpolación de cadenas | Hello, {name}! You have {n} items. (entre comillas invertidas) |
| Interpolar una expresión | Total: {price * qty} (entre comillas invertidas) |
| Continuar un bucle | for _, v in xs do if v < 0 then continue end end |
| Expresión if-then-else | local label = if hp > 0 then "alive" else "dead" |
| Expresión con else-if encadenado | local t = if n > 0 then "pos" elseif n < 0 then "neg" else "zero" |
| Literales binarios / con separador | 0b1010, 1_000_000 |
Extras de biblioteca y diferencias con Lua
Funciones que Luau añade a la biblioteca estándar y funciones de Lua que elimina.
| Elemento | Detalle |
|---|---|
| Buscar un valor en un array | table.find(xs, 42) -- índice o nil |
| Copia superficial | local copy = table.clone(t) |
| Hacer inmutable / comprobar | table.freeze(t), table.isfrozen(t) |
| Preasignar un array | table.create(10, 0) |
| Clamp / round / sign | math.clamp(x, 0, 1), math.round(x), math.sign(x) |
| Operaciones de bits | bit32.band(a, b), bit32.lshift(a, 1) |
| Eliminado por aislamiento | io, package, loadstring, loadfile, dofile |
| Obsoleto pero aún presente | getfenv, setfenv (desactivan optimizaciones) |
| No existe en Luau | goto / etiquetas (Luau se basa en Lua 5.1) |
| Leer stdin en Coddy | io.read() funciona aquí: Coddy lo restaura sobre Luau |
| Extensión de archivo | main.luau (.lua también funciona) |
| Solo Roblox, no Luau base | game, workspace, Instance.new, task.wait |
Luau es Lua 5.1 más un sistema de tipos gradual: el lenguaje que Roblox creó y liberó como código abierto. Esta chuleta de Luau cubre lo que *no* es Lua puro: anotaciones de tipo, tablas tipadas, uniones y tipos literales, genéricos, aserciones de tipo y el azúcar sintáctico que añade Luau (+=, interpolación de cadenas, continue, expresiones if-then-else). Para todo lo que comparten ambos lenguajes - tablas, metatablas, corrutinas, la biblioteca de cadenas - ten a mano la chuleta de Lua.
Todo lo que hay aquí es Luau estándar, ejecutable con la CLI luau y verificable con luau-analyze. Copia lo que necesites o pruébalo en vivo en el playground de Luau, sin instalar nada. ¿Empiezas con el sistema de tipos? El curso interactivo gratuito de Luau de Coddy lo construye lección a lección.
Preguntas frecuentes sobre la chuleta de Luau
¿Esta chuleta de Luau es gratis?
¿Luau tiene el operador +=?
+=, -=, *=, /=, //=, %=, ^= y ..= para concatenar cadenas. Así que hp += 10 es Luau válido (y código válido de Roblox), mientras que en Lua 5.1 tienes que escribir hp = hp + 10. Ojo: en Luau no existen ++ ni --.¿Cuál es la diferencia entre Lua y Luau?
continue, expresiones if-then-else, división entera //, iteración generalizada (for i, v in t do) y funciones como table.find, table.clone y table.freeze. Por aislamiento elimina loadstring, loadfile, dofile y las bibliotecas io y package, y no tiene goto porque se basa en 5.1. La mayoría del código Lua normal funciona sin cambios como Luau.¿Cómo activo la verificación de tipos en Luau?
--!strict comprueba todo e infiere de forma agresiva, --!nonstrict (el valor por defecto) solo comprueba lo que anotaste y --!nocheck desactiva la comprobación. Fuera del editor, ejecuta luau-analyze main.luau para verificar tipos sin ejecutar, y luau main.luau para ejecutar.¿Se escribe interface en Luau como en TypeScript?
interface. Las formas de objeto se escriben como tipos de tabla y se nombran con type: type User = { name: string, age: number? }. Combina formas con & en lugar de extends y usa export type para que otros módulos puedan usarla.¿Esta chuleta es lo mismo que programar en Roblox?
game, workspace, Instance.new, servicios, eventos), que es una biblioteca sobre el lenguaje y la documenta Roblox, no Luau.¿Dónde puedo ejecutar estos fragmentos de Luau?
luau real en tu navegador, con soporte de stdin, así que puedes pegar cualquier fila de esta página y pulsar Ejecutar. Para práctica estructurada, el curso interactivo de Luau cubre el mismo material con ejercicios, proyectos y certificado.