Luau は、タイプアノテーションとタイプ推論の使用を通じて、段階的なタイプシステムをサポートします。これらの種類は、スクリプトエディタ でより良い警告、エラー、および提案を提供するために使用されます。
タイプを定義す入力
type キーワードを使用して、独自のタイプを定義します:
type Vector2 = {x: number, y: number}
推論モード
Script の最初の行に設定できる Luau タイプ推論モードは 3つあります:
- --!nocheck — タイプをチェックしない。
- --!nonstrict — 明示的にアノテーションされている場合にのみ変数タイプを主張します。
- --!strict — 推論されたか明示的にアノテーションされたタイプに基づいて、すべてのタイプを主張します。
--!nonstrict および --!strict モードは、変数と関数の種類チェッカーの厳密度を検知およびチェックする方法を制御します。スクリプトのタイプミスマッチは、スクリプトエディタ で強調され、スクリプト分析 ウィンドウで警告として表示されます。
タイプ
タイプアノテーションは、ローカル変数の後に : オペレータを使用して定義でき、タイプ定義で続きます。デフォルトでは、nonstrict モードで、すべての変数にタイプ any が割り当てられます。
local foo: string = "bar"local x: number = 5
アノテーションで使用できる 4つのプリミティブタイプがあります:
- nil - 値なし
- boolean - true or 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 を使用せずに文字値にストリングやブールをキャストできます:
local alwaysHelloWorld: "Hello world!" = "Hello world!"alwaysHelloWorld = "Just hello!" -- タイプエラー:「Just hello!」を「Hello world!」に変換できませんlocal alwaysTrue: true = false -- Type error: Type 'false' could not be converted into 'true'
タイプキャスト
時々、タイプチェッカーを助けるために、:: オペレータを使用して値を異なるタイプに明示的にキャストする必要があるかもしれません:
local myNumber = 1local myString: stringmyString = myNumber -- オーケーではない; タイプ変換エラーmyString = myNumber :: any -- OK; すべての式を 'any' にキャストできますlocal myFlag = myNumber :: boolean -- Not OK; types are unrelated
機能タイプ付け
次の機能を考えてください:
local function add(x, y)
return x + y
end
この機能は x を y に追加しますが、1つまたは両方が文字列の場合エラーが発生します。Luauは、この関数が数字のみを使用できることを知らない。このカテゴリの問題を防ぐには、パラメータにタイプを追加してください:
local function add(x: number, y: number)
return x + y
end
Luau は今、機能が 2つの数字を受け取り、数字以外の何かを機能に渡そうとすると警告を表示することを知っています:
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 タイプはありません;代わりに、テーブルタイプは {} 構文を使用して定義されます。テーブルを定義する方法の 1つは、リストタイプを定義する {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
予想通り、この関数は任意の値を取ることができ、タイプチェッカーは 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)
そして今、2行目がタイプエラーを発生させます。
print(addLotsOfNumbers(1, 2, 3, 4, 5))print(addLotsOfNumbers(1, 2, "car", 4, 5)) -- タイプエラー: 文字列を数字に変換できませんでした
しかし、機能型定義を書いているときにはこれは機能しません:
type addLotsOfNumbers = (...: number) -> number -- Expected type, got ':'
代わりに、syntax ...type を使用して変数入力を定義します。
type addLotsOfNumbers = (...number) -> number
連合と交差点
ユニオンまたはインターセクションを使用して、タイプを 2つ以上のタイプに定義できます:
type numberOrString = number | stringtype type1 = {foo: string}type type2 = {bar: number}type type1and2 = type1 & type2 -- {foo: 文字列tring} と {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 を使用する方法の 1つは、setmetatable 内の typeof 関数でメタテーブルタイプを定義することです:
type Vector = typeof(setmetatable({}::{x: number,y: number}, {}::{__add: (Vector, Vector|number) -> Vector}))-- Vector + Vector would return a Vector type
ジェネリック
ジェネリックは、タイプの基本レベルパラメータです。以下の State オブジェクトを考えてください:
local State = {Key = "TimesClicked",Value = 0}
ジェネリックがないと、このオブジェクトのタイプは次のようになります:
type State = {Key: string,Value: number}
しかし、Value のタイプが受信値に基づいていることを望むかもしれません、そこにジェネリックが登場するのです:
type GenericType<T> = T
The <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}
機能ジェネリック
機能はまた、ジェネリックを使用できます。State 例では、機能の入力引数から T の値を推測します。
一般的な関数を定義するには、機能名に <> を追加してください:
local function State<T>(key: string, value: T): State<T>
return {
Key = key,
Value = value
}
end
local Activated = State("Activated", false) -- 状態<bool>
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()