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?
Sí. Esta chuleta de Luau es completamente gratuita y no requiere registro. Guárdala para la próxima vez que necesites la sintaxis de una unión, un genérico o una tabla tipada.
¿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. El curso Roblox Game Scripting enseña esa API con scripts que se ejecutan en un pequeño juego al estilo Roblox en tu navegador.¿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.