類型檢查

*此內容是使用 AI(Beta 測試版)翻譯,可能含有錯誤。若要以英文檢視此頁面,請按一下這裡

Luau 支援使用類型屬性和類型擷取來提供更好的警告、錯誤和建議在 指令編輯器 中。這些類型用於提供更好的警告、錯誤和建議在 指令編輯器 中。

定義類型

使用 type 關鍵字來定義您自己的類型:


type Vector2 = {x: number, y: number}

模式減少

有三種 Luau 類型的預設模式可以在 Script 的第一行設置:

  • --!nocheck - 不要檢查類型
  • --!nonstrict - 所有腳本的預設模式,只有明確指定類型才會擁有變數類型
  • --!strict - 建立所有類型,基於預期或明示的類輸入

類型檢查器的預設模式為 --!nonstrict 。其他兩個模式控制類型檢查器是否嚴格對待類型檢查器在 inferring 和檢查類型對變量和函數的類型進行檢查。任何類型錯誤都會在 指令編輯器 中標示為警告在 指令分析 窗口中顯示。

類型

可以使用 : 操作定義類型標誌,在本地變量後,跟隨類型定義。 預設情況下,在 nonstrict 模式下,所有變量都被指定為類型 any


local foo: string = "bar"
local x: number = 5

有四種原始類型可以在寫真中使用:

  • nil - 沒有值
  • boolean - truefalse
  • number - 數字值
  • string - 文字

內部 Roblox 中,所有類別、資料類型和數值都有自己的類型,您可以檢查對:


local somePart: Part = Instance.new("Part")
local brickColor: BrickColor = somePart.BrickColor
local material: Enum.Material = somePart.Material

要將類型選項,請在 ? 在標籤的結束:


local foo: string? = nil

這將允許變數是指定的類型 (在此情況下 stringnil ) 或 vil 。

字符型

您也可以使用 stringboolean 來傳送字串和Boolean值,而不是使用 number1 和 1>number11>:


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 = 1
local myString: string
myString = myNumber -- 不 OK;輸入轉換錯誤
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) -> number
type FindSource = (script: BaseScript, pattern: string) -> (string, number)

桌子類型

Luau 不具有 table 輸入;相反,桌子類型是使用 {} 語法定義的。一種定義桌子的方法是使用 {type} 語法,這是一種清單輸入。


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

如期所欲,此功能可以取得任何值,而 typechecker 不會提出警告,如果您提供一種不可使用的類輸入,例如 string


print(addLotsOfNumbers(1, 2, 3, 4, 5)) -- 15
print(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)) -- 類型錯誤:字串無法轉換為數字

但是,此定義類型的定義時不適用:


type addLotsOfNumbers = (...: number) -> number -- Expected type, got ':'

相反,使用語法 ...type 來定義一種變體類輸入。


type addLotsOfNumbers = (...number) -> number

聯絡和交叉

您甚至可以使用 union 或交叉點來定義類型為兩個或更多類型:


type numberOrString = number | string
type 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 的一個方法是使用 setmetatabletypeof 功能內定義一個 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>1>T 表示可以設置為任何類型的類型。最好的方法是將此視為替換類輸入。 Errors: Error: <T>1>T Severity: major ---


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}

generics 也可以在括號內有多個替換。


type Map<K, V> = {[K]: V}

要從以前的 State 對象重新工作,以使用一般類輸入:


type State<T> = {
Key: string,
Value: T
}

功能一覽

函數也可以使用通用。 The State 範例從函數的來自參數中擷取 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()