Luau支持通过使用类型注释和类型推荐提供更好的警告、错误和建议在脚本编辑器中使用。
定义类型
使用 type 关键字定义您自己的类型:
type Vector2 = {x: number, y: number}
infer 模式
在 Script 的第一行上设置三个 Luau 类型 infer 模式:
- --!nocheck - 不要检查类型
- --!nonstrict - 对于所有脚本的默认模式,只会声明变量类型,如果它们是明示的
- --!strict - 使用默认或明示的类型来确认所有类输入
类型检查器的默认模式是 --!nonstrict 。其他两个模式控制类型检查器是否严格对待变量和函数的 inferring 和检查类型。任何类型不匹配在脚本中都会在 脚本编辑器 中显示为警告在 脚本分析 窗口。
类型
使用 : 操作后的本地变量后,可以定义类型注释。默认情况下,在 nonstrict 模式下,所有变量都被分配为类型 any 。
local foo: string = "bar"local x: number = 5
有四种原始类型可以用于注释:
- nil - 无价值
- boolean - true 或 false
- number - 数字值
- string - 文本
在 Roblox 中,所有类别、数据类型和数量都有自己的类型,您可以根据以下进行检查:
local somePart: Part = Instance.new("Part")local brickColor: BrickColor = somePart.BrickColorlocal material: Enum.Material = somePart.Material
要使一个类型为可选,请在注释结束使用一个 ? :
local foo: string? = nil
这将允许变量是指定的类型 (在此例中 string 或 nil 。
字符串类型
您还可以使用 string 和 boolean 来将字符串和Boolean变成文本值:
local alwaysHelloWorld: "Hello world!" = "Hello world!"alwaysHelloWorld = "Just hello!" -- 输入错误:输入 “你好!” 无法转换为 “你好,世界!”local alwaysTrue: true = false -- Type error: Type 'false' could not be converted into 'true'
类型 Casts
有时,您可能需要通过明确将值 Cast 到不同的类型来为类型检查器提供助力:
local myNumber = 1local myString: stringmyString = myNumber -- 不好,请输入转换错误myString = myNumber :: any -- 好的;所有表达都可以投入 “任何”local myFlag = myNumber :: boolean -- Not OK; types are unrelated
函数型号
考虑以下函数:
local function add(x, y)
return x + y
end
此函数将 x 添加到 y ,但如果其中一个或两个是字符串,则会发生错误。Luau 不知道这个函数只能使用数字。为了防止此类问题,请将类型添加到参数:
local function add(x: number, y: number)
return x + y
end
Luau 现在知道函数取两个数字,如果你尝试将任何非数字传入函数,它将发出警告:
add(5, 10)add(5, "foo") -- Type error: string could not be converted into number
要定义一个返回输入,请在函数定义的末尾放置一个 : 操作器:
local function add(x: number, y: number): number
要将多个类型返回,请将类型放在括号中:
local function FindSource(script: BaseScript, pattern: string): (string, number)
return 42, true -- 类型错误
end
定义功能型
功能型可以通过使用语法 (in) -> out 定义。使用上一例的函数,函数的类型是:
type add = (x: number, y: number) -> numbertype FindSource = (script: BaseScript, pattern: string) -> (string, number)
表类型
Luau 不具有 table 类输入,而是使用 {} 语法定义表类型。 使用 {type} 语法定义表的一个方法是使用 1> typ输入1> 语法,这会定义一个列类输入。
local numbers: {number} = {1, 2, 3, 4, 5}local characterParts: {Instance} = LocalPlayer.Character:GetChildren()
使用 {[indexType]: valueType} 定义索引类型:
local numberList: {[string]: number} = {Foo = 1,Baz = 10}numberList["bar"] = true -- Type error: boolean can't convert to number
桌子可以有明确的字符串索引在类输入中定义。
type Car = {
Speed: number,
Drive: (Car) -> ()
}
local function drive(car)
-- 总是遵守速度限制
end
local taxi: Car = {Speed = 30, Drive = drive}
变体
这里是一个计算任意数量的函数的函数:
local function addLotsOfNumbers(...)
local sum = 0
for _, v in {...} do
sum += v
end
return sum
end
如期待,此函数可以接受任何值,并且类型检查器不会提出警告,如果您提供无效的输入,例如 string 。
print(addLotsOfNumbers(1, 2, 3, 4, 5)) -- 15print(addLotsOfNumbers(1, 2, "car", 4, 5)) -- Attempt to add string to number
相反,将类型分配到 ... ,就像你分配任何其他输入一样:
local function addLotsOfNumbers(...: number)
现在,第二行会引发类型错误。
print(addLotsOfNumbers(1, 2, 3, 4, 5))print(addLotsOfNumbers(1, 2, "car", 4, 5)) -- 类型错误:string 无法转换为数字
但是,这不会在写功能类型定义时工作:
type addLotsOfNumbers = (...: number) -> number -- Expected type, got ':'
使用语法 ...type 定义变体类输入。
type addLotsOfNumbers = (...number) -> number
联合和交叉
您甚至可以使用联合或交叉来定义类型为两个或多个类型:
type numberOrString = number | stringtype type1 = {foo: string}type type2 = {bar: number}type type1and2 = type1 & type2 -- :{foo: strin字符串} & {bar: number}local numString1: numberOrString = true -- 类型错误local numString2: type1and2 = {foo = "hello", bar = 1}
定义默认类型
您可以在类型定义中使用 typeof 函数来表示隐含类型:
type Car = typeof({Speed = 0,Wheels = 4}) --> Car: {Speed: number, Wheels: number}
使用 typeof 的一个方法是使用 setmetatable 在 typeof 函数中定义一个 metatable 型。
type Vector = typeof(setmetatable({}::{x: number,y: number}, {}::{__add: (Vector, Vector|number) -> Vector}))-- Vector + Vector would return a Vector type
通用
generics 是类型的基础参数。考虑以下 State 对象:
local State = {Key = "TimesClicked",Value = 0}
无论通用,该对象的类型将是以下:
type State = {Key: string,Value: number}
但是,您可能想要类型为 Value 基于收入值,这是类型来自:
type GenericType<T> = T
<T> 表示可以设置为任何东西的类型。最好的方法是将其视图为替换输入。
type List<T> = {T}local Names: List<string> = {"Bob", "Dan", "Mary"} -- 类型变为 {字符串tring}local Fibonacci: List<number> = {1, 1, 2, 3, 5, 8, 13} -- Type becomes {number}
通用也可以在括号内有多个替换。
type Map<K, V> = {[K]: V}
要从以前的 State 对象重工,使用通用类输入:
type State<T> = {Key: string,Value: T}
函数公用
函数还可以使用通用。 The State 例子从函数的参数中 infer T 值。
要定义一个通用函数,请在函数名中加入一个 <> 。
local function State<T>(key: string, value: T): State<T>
return {
Key = key,
Value = value
}
end
local Activated = State("Activated", false) -- 状态<button>
local TimesClicked = State("TimesClicked", 0) -- State<number>
类型导出
要使类型可以在 ModuleScript 之外使用,请使用 export 关键字:
在 ReplicatedStorage 中类型模块
export type Cat = {Name: string,Meow: (Cat) -> ()}
使用类型模块的脚本
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()