Kiểm tra kiểu

*Nội dung này được dịch bằng AI (Beta) và có thể có lỗi. Để xem trang này bằng tiếng Anh, hãy nhấp vào đây.

Luau hỗ trợ một hệ thống kiểu dần thông qua việc sử dụng chú thích kiểu và suy diễn kiểu. Những kiểu này được sử dụng để cung cấp các cảnh báo, lỗi và gợi ý tốt hơn trong Trình chỉnh sửa Script.

Định nghĩa một kiểu

Sử dụng từ khóa type để định nghĩa các kiểu của riêng bạn:


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

Chế độ suy diễn

Có ba chế độ suy diễn kiểu trong Luau có thể được thiết lập trên dòng đầu tiên của một Script:

  • --!nocheck — Không kiểm tra kiểu.
  • --!nonstrict — Chỉ đảm bảo kiểu của các biến nếu chúng được chú thích rõ ràng.
  • --!strict — Đảm bảo tất cả các kiểu dựa trên kiểu đã suy diễn hoặc chú thích rõ ràng.

Các chế độ --!nonstrict--!strict kiểm soát mức độ nghiêm ngặt của bộ kiểm tra kiểu khi suy diễn và kiểm tra kiểu cho các biến và hàm. Mọi sự không khớp kiểu trong các script sẽ được hiển thị trong Trình chỉnh sửa Script và hiện lên như các cảnh báo trong cửa sổ Phân tích Script.

Để thiết lập một chế độ mặc định cho tất cả các script mà bạn có thể ghi đè khi cần, hãy xem Workspace.LuauTypeCheckMode.

Các kiểu

Một chú thích kiểu có thể được định nghĩa bằng cách sử dụng toán tử : sau một biến cục bộ, theo sau là một định nghĩa kiểu. Mặc định, trong chế độ nonstrict, tất cả các biến được gán kiểu any.


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

Có bốn kiểu nguyên thủy có thể được sử dụng trong một chú thích:

  • nil - không có giá trị
  • boolean - true hoặc false
  • number - một giá trị số
  • string - văn bản

Trong Roblox, tất cả các lớp, loại dữ liệu và enum đều có các kiểu riêng mà bạn có thể kiểm tra:


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

Để làm cho một kiểu trở thành tùy chọn, sử dụng ký tự ? ở cuối chú thích:


local foo: string? = nil

Điều này sẽ cho phép biến có thể là kiểu được chỉ định (trong trường hợp này là string) hoặc nil.

Kiểu literal

Bạn cũng có thể ép kiểu chuỗi và boolean thành các giá trị literal thay vì sử dụng stringboolean:


local alwaysHelloWorld: "Hello world!" = "Hello world!"
alwaysHelloWorld = "Just hello!" -- Lỗi kiểu: Kiểu '"Just hello!"' không thể chuyển đổi thành '"Hello world!"'
local alwaysTrue: true = false -- Lỗi kiểu: Kiểu 'false' không thể chuyển đổi thành 'true'

Ép kiểu

Đôi khi, bạn có thể cần hỗ trợ bộ kiểm tra kiểu bằng cách ép kiểu một giá trị thành kiểu khác với toán tử :::


local myNumber = 1
local myString: string
myString = myNumber -- Không OK; lỗi chuyển đổi kiểu
myString = myNumber :: any -- OK; tất cả các biểu thức có thể được ép kiểu thành 'any'
local myFlag = myNumber :: boolean -- Không OK; các kiểu không liên quan

Kiểu hàm

Xem xét hàm sau:


local function add(x, y)
return x + y
end

Hàm này cộng x với y, nhưng báo lỗi nếu một hoặc cả hai là chuỗi. Luau không biết rằng hàm này chỉ có thể sử dụng số. Để ngăn chặn loại vấn đề này, hãy thêm kiểu cho các tham số:


local function add(x: number, y: number)
return x + y
end

Luau giờ đây biết rằng hàm này nhận hai số và sẽ ném ra một cảnh báo nếu bạn cố gắng truyền bất cứ điều gì không phải là số vào hàm:


add(5, 10)
add(5, "foo") -- Lỗi kiểu: chuỗi không thể chuyển đổi thành số

Để định nghĩa một kiểu trả về, đặt một toán tử : ở cuối định nghĩa hàm:


local function add(x: number, y: number): number

Để trả về nhiều kiểu, đặt các kiểu trong dấu ngoặc đơn:


local function FindSource(script: BaseScript, pattern: string): (string, number)
return 42, true -- Lỗi kiểu
end

Định nghĩa một kiểu hàm

Một kiểu hàm có thể được định nghĩa bằng cách sử dụng cú pháp (in) -> out. Sử dụng các hàm từ các ví dụ trước, các kiểu của các hàm là:


type add = (x: number, y: number) -> number
type FindSource = (script: BaseScript, pattern: string) -> (string, number)

Các kiểu bảng

Luau không có kiểu table; thay vào đó, các kiểu bảng được định nghĩa bằng cú pháp {}. Một cách để định nghĩa các bảng là sử dụng cú pháp {type}, định nghĩa một kiểu danh sách.


local numbers: {number} = {1, 2, 3, 4, 5}
local characterParts: {Instance} = LocalPlayer.Character:GetChildren()

Định nghĩa các kiểu chỉ mục sử dụng {[indexType]: valueType}:


local numberList: {[string]: number} = {
Foo = 1,
Baz = 10
}
numberList["bar"] = true -- Lỗi kiểu: boolean không thể chuyển đổi thành number

Các bảng cũng có thể có các chỉ mục chuỗi rõ ràng được định nghĩa trong một kiểu.


type Car = {
Speed: number,
Drive: (Car) -> ()
}
local function drive(car)
-- Luôn đi đúng tốc độ quy định
end
local taxi: Car = {Speed = 30, Drive = drive}

Variadics

Đây là một hàm tính tổng của một số lượng số tùy ý:


local function addLotsOfNumbers(...)
local sum = 0
for _, v in {...} do
sum += v
end
return sum
end

Như mong đợi, hàm này có thể nhận bất kỳ giá trị nào, và bộ kiểm tra kiểu sẽ không đưa ra cảnh báo nếu bạn cung cấp một kiểu không hợp lệ, chẳng hạn như một string.


print(addLotsOfNumbers(1, 2, 3, 4, 5)) -- 15
print(addLotsOfNumbers(1, 2, "car", 4, 5)) -- Cố gắng cộng chuỗi với số

Thay vào đó, bạn gán một kiểu cho ..., giống như cách bạn gán bất kỳ kiểu nào khác:


local function addLotsOfNumbers(...: number)

Và bây giờ, dòng thứ hai sẽ gây ra một lỗi kiểu.


print(addLotsOfNumbers(1, 2, 3, 4, 5))
print(addLotsOfNumbers(1, 2, "car", 4, 5)) -- Lỗi kiểu: chuỗi không thể chuyển đổi thành số

Tuy nhiên, điều này không hoạt động khi viết định nghĩa kiểu hàm:


type addLotsOfNumbers = (...: number) -> number -- Kiểu mong đợi, nhận được ':'

Thay vào đó, sử dụng cú pháp ...type để định nghĩa một kiểu variadic.


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

Liên hợp và giao nhau

Bạn thậm chí có thể định nghĩa một kiểu là hai hoặc nhiều kiểu bằng cách sử dụng liên hợp hoặc giao nhau:


type numberOrString = number | string
type type1 = {foo: string}
type type2 = {bar: number}
type type1and2 = type1 & type2 -- {foo: string} & {bar: number}
local numString1: numberOrString = true -- Lỗi kiểu
local numString2: type1and2 = {foo = "hello", bar = 1}

Định nghĩa một kiểu đã suy diễn

Bạn có thể sử dụng hàm typeof trong một định nghĩa kiểu cho các kiểu đã suy diễn:


type Car = typeof({
Speed = 0,
Wheels = 4
}) --> Car: {Speed: number, Wheels: number}

Một cách để sử dụng typeof là định nghĩa một kiểu metatable bằng cách sử dụng setmetatable bên trong hàm typeof:


type Vector = typeof(setmetatable({}::{
x: number,
y: number
}, {}::{
__add: (Vector, Vector|number) -> Vector
}))
-- Vector + Vector sẽ trả về một kiểu Vector

Generics

Generics ở cấp độ cơ bản là các tham số cho kiểu. Xem xét đối tượng State sau:


local State = {
Key = "TimesClicked",
Value = 0
}

Không có generics, kiểu cho đối tượng này sẽ như sau:


type State = {
Key: string,
Value: number
}

Tuy nhiên, bạn có thể muốn kiểu cho Value dựa trên giá trị đầu vào, đó là nơi generics ra đời:


type GenericType<T> = T

Chữ <T> biểu thị một kiểu có thể được đặt thành bất kỳ gì. Cách tốt nhất để hình dung điều này là như một kiểu thay thế.


type List<T> = {T}
local Names: List<string> = {"Bob", "Dan", "Mary"} -- Kiểu trở thành {string}
local Fibonacci: List<number> = {1, 1, 2, 3, 5, 8, 13} -- Kiểu trở thành {number}

Generics cũng có thể có nhiều thay thế bên trong dấu ngoặc.


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

Để làm lại đối tượng State từ trước để sử dụng một kiểu generic:


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

Generics trong hàm

Các hàm cũng có thể sử dụng generics. Ví dụ State suy diễn giá trị của T từ các đối số đầu vào của hàm.

Để định nghĩa một hàm generic, thêm <> vào tên hàm:


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>

Xuất kiểu

Để kiểu có thể được sử dụng bên ngoài một ModuleScript, sử dụng từ khóa export:

Types Module in ReplicatedStorage

export type Cat = {
Name: string,
Meow: (Cat) -> ()
}
Script Using the Types Module

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Types = require(ReplicatedStorage.Types)
local newCat: Types.Cat = {
Name = "metatablecat",
Meow = function(self)
print(`{self.Name} nói meow`)
end
}
newCat:Meow()
©2026 Roblox Corporation. Roblox, logo Roblox và Powering Imagination là các nhãn hiệu đã đăng ký và chưa đăng ký của chúng tôi tại Hoa Kỳ và các quốc gia khác.