Luau soporta un sistema de tipo gradual a través del uso de anotaciones de tipo y inferencia de tipo.Estos tipos se usan para proporcionar advertencias, errores y sugerencias mejores en el editor de scripts.
Define un introducir
Usa la palabra clave type para definir tus propios tipos:
type Vector2 = {x: number, y: number}
Modos de inferencia
Hay tres modos de inferencia de tipo Luau que se pueden establecer en la primera línea de un Script :
- --!nocheck — No verifique los tipos.
- --!nonstrict — Solo afirma tipos de variables si se anotan explícitamente.
- --!strict — Afirma todos los tipos basados en el introducirinferido o explícitamente anotado.
Los modos --!nonstrict y --!strict controlan qué tan estricto es el comprobador de tipos al inferir y verificar tipos para variables y funciones.Cualquier tipo de coincidencias en los scripts se resalta en el Editor de scripts y se muestra como advertencias en la ventana Análisis de scripts.
Tipos
Una anotación de tipo se puede definir usando el operador : después de una variable local, seguida de una definición de tipo.Por defecto, en el modo nonstrict , todas las variables se asignan el tipo any .
local foo: string = "bar"local x: number = 5
Hay cuatro tipos primitivos que se pueden utilizar en una anotación:
- nil - sin valor
- boolean - true or false
- number - un valor numérico
- string - texto
Dentro de Roblox, todas las Clases, tipos de datos y enunciados tienen sus propios tipos que puedes comparar:
local somePart: Part = Instance.new("Part")local brickColor: BrickColor = somePart.BrickColorlocal material: Enum.Material = somePart.Material
Para hacer un tipo opcional, use un ? al final de la anotación:
local foo: string? = nil
Esto permitirá que la variable sea el tipo especificado (en este caso string ) o nil .
Tipos literales
También puedes lanzar cadenas y booleanos a valores literales en lugar de usar string y boolean :
local alwaysHelloWorld: "Hello world!" = "Hello world!"alwaysHelloWorld = "Just hello!" -- Error de tipo: el tipo 'Solo hola!' no se pudo convertir en 'Hola mundo!'local alwaysTrue: true = false -- Type error: Type 'false' could not be converted into 'true'
Tipos de lanzamiento
A veces, es posible que necesite ayudar al comprobador de tipos a expresar explícitamente un valor a un tipo diferente con el operador :::
local myNumber = 1local myString: stringmyString = myNumber -- No está bien; escriba el error de conversiónmyString = myNumber :: any -- OK; todas las expresiones se pueden lanzar a 'cualquiera'local myFlag = myNumber :: boolean -- Not OK; types are unrelated
Tipado de funciones
Considera la siguiente función:
local function add(x, y)
return x + y
end
Esta función agrega x a y, pero falla si uno o ambos son una cadena.Luau no sabe que esta función solo puede usar números.Para prevenir esta categoría de problema, agregue tipos a los parámetros:
local function add(x: number, y: number)
return x + y
end
Luau ahora sabe que la función toma dos números y lanza una advertencia si intentas pasar cualquier cosa que no sea un número a la función:
add(5, 10)add(5, "foo") -- Type error: string could not be converted into number
Para definir un introducirde devolución, pon un operador : al final de la definición de la función:
local function add(x: number, y: number): number
Para devolver múltiples tipos, coloque los tipos en paréntesis:
local function FindSource(script: BaseScript, pattern: string): (string, number)
return 42, true -- Errores de tipo
end
Define un introducirfuncional
Un tipo funcional se puede definir usando la sintaxis (in) -> out. Usando las funciones de los ejemplos anteriores, los tipos de las funciones son:
type add = (x: number, y: number) -> numbertype FindSource = (script: BaseScript, pattern: string) -> (string, number)
Tipos de tabla
Luau no tiene un tipo table tipo; en cambio, los tipos de tabla se definen usando la sintaxis {}.Una forma de definir tablas es usando la sintaxis {type}, que define un introducirde lista.
local numbers: {number} = {1, 2, 3, 4, 5}local characterParts: {Instance} = LocalPlayer.Character:GetChildren()
Define tipos de índice usando {[indexType]: valueType} :
local numberList: {[string]: number} = {Foo = 1,Baz = 10}numberList["bar"] = true -- Type error: boolean can't convert to number
Las tablas también pueden tener índices de cuerda explícitos definidos en un introducir.
type Car = {
Speed: number,
Drive: (Car) -> ()
}
local function drive(car)
-- Siempre vaya al límite de velocidad
end
local taxi: Car = {Speed = 30, Drive = drive}
Variadicos
Aquí hay una función que calcula la suma de una cantidad arbitraria de números:
local function addLotsOfNumbers(...)
local sum = 0
for _, v in {...} do
sum += v
end
return sum
end
Como se esperaba, esta función puede tomar cualquier valor, y el comprobador de tipos no emitirá una advertencia si proporciona un introducirinválido, como un string .
print(addLotsOfNumbers(1, 2, 3, 4, 5)) -- 15print(addLotsOfNumbers(1, 2, "car", 4, 5)) -- Attempt to add string to number
En cambio, asigne un tipo al ..., al igual que cómo asigna cualquier otro introducir:
local function addLotsOfNumbers(...: number)
Y ahora, la segunda línea levanta un error de tipo.
print(addLotsOfNumbers(1, 2, 3, 4, 5))print(addLotsOfNumbers(1, 2, "car", 4, 5)) -- Error de tipo: la cadena no se pudo convertir en número
Sin embargo, esto no funciona al escribir una definición de tipo funcional:
type addLotsOfNumbers = (...: number) -> number -- Expected type, got ':'
En cambio, utilice la sintaxis ...type para definir un introducirvariado.
type addLotsOfNumbers = (...number) -> number
Uniones y intersecciones
Incluso puedes definir un tipo como dos o más tipos usando una unión o intersección:
type numberOrString = number | stringtype type1 = {foo: string}type type2 = {bar: number}type type1and2 = type1 & type2 -- {foo: cadena} y {bar: number}local numString1: numberOrString = true -- Error de tipolocal numString2: type1and2 = {foo = "hello", bar = 1}
Define un introducirinferido
Puedes usar la función typeof en una definición de tipo para tipos inferidos:
type Car = typeof({Speed = 0,Wheels = 4}) --> Car: {Speed: number, Wheels: number}
Una forma de usar typeof es definir un tipo metatable usando setmetatable dentro de la función typeof:
type Vector = typeof(setmetatable({}::{x: number,y: number}, {}::{__add: (Vector, Vector|number) -> Vector}))-- Vector + Vector would return a Vector type
Generéricos
Los genéricos son parámetros de nivel básico para tipos. Considere el siguiente objeto State :
local State = {Key = "TimesClicked",Value = 0}
Sin genéricos, el tipo para este objeto sería el siguiente:
type State = {Key: string,Value: number}
Sin embargo, es posible que desees que el tipo para Value se base en el valor entrante, donde es donde entran los genéricos:
type GenericType<T> = T
El <T> indica un tipo que se puede establecer a cualquier cosa. La mejor manera de visualizar esto es como un introducirde sustitución.
type List<T> = {T}local Names: List<string> = {"Bob", "Dan", "Mary"} -- El tipo se convierte en {cadena}local Fibonacci: List<number> = {1, 1, 2, 3, 5, 8, 13} -- Type becomes {number}
Los genéricos también pueden tener múltiples sustituciones dentro de los paréntesis.
type Map<K, V> = {[K]: V}
Para reelaborar el objeto State de antes para usar un introducirgenérico:
type State<T> = {Key: string,Value: T}
Generadores de funciones
Las funciones también pueden usar genéricos. El ejemplo State infiere el valor de T de los argumentos entrantes de la función.
Para definir una función genérica, agregue un <> a el nombre de la función:
local function State<T>(key: string, value: T): State<T>
return {
Key = key,
Value = value
}
end
local Activated = State("Activated", false) -- Estado< boolean >
local TimesClicked = State("TimesClicked", 0) -- State<number>
Tipo de exportaciones
Para hacer que un tipo se pueda usar fuera de un ModuleScript , use la palabra clave export:
Tipos de módulo en ReplicatedStorage
export type Cat = {Name: string,Meow: (Cat) -> ()}
Script que utiliza el módulo de tipos
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Types = require(ReplicatedStorage.Types)
local newCat: Types.Cat = {
Name = "metatablecat",
Meow = function(self)
print(`{self.Name} said meow`)
end
}
newCat:Meow()