Luau mendukung sistem tipe bertahap melalui penggunaan anotasi tipe dan inferensi tipe. Tipe ini digunakan untuk memberikan peringatan, kesalahan, dan saran yang lebih baik di Editor Skrip.
Mendefinisikan tipe
Gunakan kata kunci type untuk mendefinisikan tipe Anda sendiri:
type Vector2 = {x: number, y: number}Metode inferensi
Ada tiga metode inferensi tipe Luau yang dapat ditetapkan di baris pertama dari Script:
- --!nocheck — Jangan periksa tipe.
- --!nonstrict — Hanya memastikan tipe variabel jika mereka dianotasi secara eksplisit.
- --!strict — Memastikan semua tipe berdasarkan tipe yang diinfer atau dianotasi secara eksplisit.
Mode --!nonstrict dan --!strict mengendalikan seberapa ketat pemeriksa tipe dengan menginfer dan memeriksa tipe untuk variabel dan fungsi. Setiap ketidakcocokan tipe dalam skrip ditandai dalam Editor Skrip dan muncul sebagai peringatan di jendela Analisis Skrip.
Untuk menetapkan mode default untuk semua skrip yang dapat Anda ganti sesuai kebutuhan, lihat Workspace.LuauTypeCheckMode.
Tipe
Anotasi tipe dapat didefinisikan menggunakan operator : setelah variabel lokal, diikuti oleh definisi tipe. Secara default, dalam mode nonstrict, semua variabel diberikan tipe any.
local foo: string = "bar"
local x: number = 5Ada empat tipe primitif yang dapat digunakan dalam anotasi:
- nil - tidak ada nilai
- boolean - true atau false
- number - nilai numerik
- string - teks
Dalam Roblox, semua kelas, tipe data, dan enum memiliki tipe mereka sendiri yang dapat Anda periksa:
local somePart: Part = Instance.new("Part")
local brickColor: BrickColor = somePart.BrickColor
local material: Enum.Material = somePart.MaterialUntuk membuat tipe opsional, gunakan ? di akhir anotasi:
local foo: string? = nilIni akan memungkinkan variabel menjadi tipe yang ditentukan (dalam hal ini string) atau nil.
Tipe literal
Anda juga dapat mengcasting string dan boolean menjadi nilai literal daripada menggunakan string dan boolean:
local alwaysHelloWorld: "Hello world!" = "Hello world!"
alwaysHelloWorld = "Just hello!" -- Kesalahan tipe: Tipe '"Just hello!"' tidak dapat dikonversi menjadi '"Hello world!"'
local alwaysTrue: true = false -- Kesalahan tipe: Tipe 'false' tidak dapat dikonversi menjadi 'true'Casting tipe
Kadang-kadang, Anda mungkin perlu membantu pemeriksa tipe dengan mengcasting nilai secara eksplisit ke tipe yang berbeda menggunakan operator :::
local myNumber = 1
local myString: string
myString = myNumber -- Tidak OK; kesalahan konversi tipe
myString = myNumber :: any -- OK; semua ekspresi dapat dicasting ke 'any'
local myFlag = myNumber :: boolean -- Tidak OK; tipe tidak terkaitPengetikan fungsi
Pertimbangkan fungsi berikut:
local function add(x, y)
return x + y
endFungsi ini menambahkan x ke y, tetapi menghasilkan kesalahan jika satu atau kedua dari mereka adalah string. Luau tidak tahu bahwa fungsi ini hanya dapat menggunakan angka. Untuk mencegah masalah kategori ini, tambahkan tipe pada parameter:
local function add(x: number, y: number)
return x + y
endLuau sekarang tahu bahwa fungsi ini mengambil dua angka dan melempar peringatan jika Anda mencoba untuk memberikan sesuatu yang bukan angka ke fungsi:
add(5, 10)
add(5, "foo") -- Kesalahan tipe: string tidak dapat dikonversi menjadi numberUntuk mendefinisikan tipe pengembalian, tempatkan operator : di akhir definisi fungsi:
local function add(x: number, y: number): numberUntuk mengembalikan beberapa tipe, tempatkan tipe dalam tanda kurung:
local function FindSource(script: BaseScript, pattern: string): (string, number)
return 42, true -- Kesalahan tipe
endMendefinisikan tipe fungsional
Tipe fungsional dapat didefinisikan dengan menggunakan sintaks (in) -> out. Menggunakan fungsi dari contoh sebelumnya, tipe dari fungsi adalah:
type add = (x: number, y: number) -> number
type FindSource = (script: BaseScript, pattern: string) -> (string, number)Tipe tabel
Luau tidak memiliki tipe table; sebaliknya, tipe tabel didefinisikan menggunakan sintaks {}. Salah satu cara untuk mendefinisikan tabel adalah menggunakan sintaks {type}, yang mendefinisikan tipe daftar.
local numbers: {number} = {1, 2, 3, 4, 5}
local characterParts: {Instance} = LocalPlayer.Character:GetChildren()Tentukan tipe indeks menggunakan {[indexType]: valueType}:
local numberList: {[string]: number} = {
Foo = 1,
Baz = 10
}
numberList["bar"] = true -- Kesalahan tipe: boolean tidak dapat dikonversi ke numberTabel juga dapat memiliki indeks string eksplisit yang didefinisikan dalam tipe.
type Car = {
Speed: number,
Drive: (Car) -> ()
}
local function drive(car)
-- Selalu pergi sesuai batas kecepatan
end
local taxi: Car = {Speed = 30, Drive = drive}Variadik
Ini adalah fungsi yang menghitung jumlah dari jumlah angka secara sewenang-wenang:
local function addLotsOfNumbers(...)
local sum = 0
for _, v in {...} do
sum += v
end
return sum
endSeperti yang diharapkan, fungsi ini dapat menerima nilai apa pun, dan pemeriksa tipe tidak akan mengeluarkan peringatan jika Anda memberikan tipe yang tidak valid, seperti string.
print(addLotsOfNumbers(1, 2, 3, 4, 5)) -- 15
print(addLotsOfNumbers(1, 2, "car", 4, 5)) -- Mencoba menambahkan string ke numberSebagai gantinya, tetapkan tipe ke ..., sama seperti cara Anda menetapkan tipe lainnya:
local function addLotsOfNumbers(...: number)Dan sekarang, baris kedua menghasilkan kesalahan tipe.
print(addLotsOfNumbers(1, 2, 3, 4, 5))
print(addLotsOfNumbers(1, 2, "car", 4, 5)) -- Kesalahan tipe: string tidak dapat dikonversi menjadi numberNamun, ini tidak berfungsi saat menulis definisi tipe fungsional:
type addLotsOfNumbers = (...: number) -> number -- Tipe yang diharapkan, mendapat ':'Sebagai gantinya, gunakan sintaks ...type untuk mendefinisikan tipe variadik.
type addLotsOfNumbers = (...number) -> numberUnion dan intersection
Anda juga dapat mendefinisikan tipe sebagai dua atau lebih tipe menggunakan union atau intersection:
type numberOrString = number | string
type type1 = {foo: string}
type type2 = {bar: number}
type type1and2 = type1 & type2 -- {foo: string} & {bar: number}
local numString1: numberOrString = true -- Kesalahan tipe
local numString2: type1and2 = {foo = "hello", bar = 1}Mendefiniskan tipe inferred
Anda dapat menggunakan fungsi typeof dalam definisi tipe untuk tipe inferred:
type Car = typeof({
Speed = 0,
Wheels = 4
}) --> Car: {Speed: number, Wheels: number}Salah satu cara menggunakan typeof adalah untuk mendefinisikan tipe metatable menggunakan setmetatable di dalam fungsi typeof:
type Vector = typeof(setmetatable({}::{
x: number,
y: number
}, {}::{
__add: (Vector, Vector|number) -> Vector
}))
-- Vector + Vector akan mengembalikan tipe VectorGenerik
Generik adalah pada tingkat dasar parameter untuk tipe. Pertimbangkan objek State berikut:
local State = {
Key = "TimesClicked",
Value = 0
}Tanpa generik, tipe untuk objek ini akan sebagai berikut:
type State = {
Key: string,
Value: number
}Namun, Anda mungkin ingin tipe untuk Value berdasarkan nilai yang masuk, yang di sinilah generik masuk:
type GenericType<T> = T<T> menunjukkan tipe yang dapat diatur menjadi apa saja. Cara terbaik untuk memvisualisasikan ini adalah sebagai tipe substitusi.
type List<T> = {T}
local Names: List<string> = {"Bob", "Dan", "Mary"} -- Tipe menjadi {string}
local Fibonacci: List<number> = {1, 1, 2, 3, 5, 8, 13} -- Tipe menjadi {number}Generik juga dapat memiliki beberapa substitusi di dalam tanda kurung.
type Map<K, V> = {[K]: V}Untuk merombak objek State dari sebelumnya agar menggunakan tipe generik:
type State<T> = {
Key: string,
Value: T
}Generik fungsi
Fungsi juga dapat menggunakan generik. Contoh State menyimpulkan nilai dari T dari argumen yang masuk ke fungsi.
Untuk mendefinisikan fungsi generik, tambahkan <> ke nama fungsi:
local function State<T>(key: string, value: T): State<T>
return {
Key = key,
Value = value
}
end
local Activated = State("Activated", false) -- State<boolean>
local TimesClicked = State("TimesClicked", 0) -- State<number>Ekspor tipe
Untuk membuat agar tipe dapat digunakan di luar ModuleScript, gunakan kata kunci export:
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} berkata meow`)
end
}
newCat:Meow()