Weryfikacja typu

*Ta zawartość została przetłumaczona przy użyciu narzędzi AI (w wersji beta) i może zawierać błędy. Aby wyświetlić tę stronę w języku angielskim, kliknij tutaj.

Luau wspiera stopniowy system typów za pomocą użycia anotacji typu i inferencji typu.Te typy są używane do dostarczania lepszych ostrzeżeń, błędów i sugestii w edytorze skryptów.

Określ wpisywać

Użyj kluczowa type słowo, aby zdefiniować własne typy:


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

Tryby inferencji

Istnieją trzy tryby inferencji typu Luau, które można ustawić na pierwszej linii Script :

  • --!nocheck — Nie sprawdzaj typów.
  • --!nonstrict — Tylko aserbuje typy zmiennych, jeśli są wyraźnie oznaczone.
  • --!strict — Twierdzi wszystkie typy na podstawie wnioskowanego lub wyraźnie oznaczonego wpisywać.

Tryby --!nonstrict i --!strict kontrolują, jak rygorystyczny jest kontroler typów przy inferowaniu i sprawdzaniu typów dla zmiennych i funkcji.Wszelkie niezgodności typu w skryptach są zaznaczone w edytorze skryptów i wyświetlane jako ostrzeżenia w oknie analizy skryptów.

Typy

Anotacja typu może być zdefiniowana za pomocą operatora : po lokalnej zmiennej, po którym następuje definicja typu.Domyślnie, w trybie nonstrict wszystkie zmienne są przypisywane typowi any.


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

Istnieją cztery typy proste, które można używać w anotacji:

  • nil - brak wartości
  • boolean - true or false
  • number - wartość liczowa
  • string - tekst

W obrębie Roblox wszystkie klasy, typy danych i enumery mają własne typy, które możesz sprawdzić:


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

Aby uczynić typ opcjonalnym, użyj ? na końcu anotacji:


local foo: string? = nil

Umożliwi to zmiennej być albo określonym typem (w tym przypadku string ) lub nil.

Typy dosłowne

Możesz również przekazać struny i booliany do dosłownych wartości zamiast używać string i boolean :


local alwaysHelloWorld: "Hello world!" = "Hello world!"
alwaysHelloWorld = "Just hello!" -- Błąd typu: Typ „Tylko cześć!” nie mógł zostać przekonwertowany na „Witaj, świat!”
local alwaysTrue: true = false -- Type error: Type 'false' could not be converted into 'true'

Typy zamków

Czasami możesz potrzebować pomocy typownika, aby wyraźnie przekazać wartość do innego typu za pomocą operatora :::


local myNumber = 1
local myString: string
myString = myNumber -- Nie OK; wprowadź błąd konwersji
myString = myNumber :: any -- OK; wszystkie wyrażenia mogą być zamienione na 'dowolne'
local myFlag = myNumber :: boolean -- Not OK; types are unrelated

Typowanie funkcji

Rozważ następną funkcję:


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

Funkcja ta dodaje x do y, ale występują błędy, jeśli jeden lub oba są ciągiem.Luau nie wie, że ta funkcja może używać tylko liczb.Aby zapobiec tej kategorii problemu, dodaj typy do parametrów:


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

Luau teraz wie, że funkcja przyjmuje dwie liczby i wyświetla ostrzeżenie, jeśli próbujesz przekazać coś, co nie jest liczbą, do funkcji:


add(5, 10)
add(5, "foo") -- Type error: string could not be converted into number

Aby określić wpisywaćzwrotu, umieść operator : na końcu definicji funkcji:


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

Aby zwrócić wiele typów, umieść rodzaje w nawiasach:


local function FindSource(script: BaseScript, pattern: string): (string, number)
return 42, true -- Błędy typu
end

Określ wpisywaćfunkcjonalny

Typ funkcjonalny można zdefiniować za pomocą składni (in) -> out. Korzystając z funkcji z poprzednich przykładów, rodzaje funkcji są:


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

Typy tabel

Luau nie ma wpisywaćtable, zamiast tego typy tabel są określone za pomocą {} słowotwórstwa.Jednym ze sposobów określania tabel jest użycie sygnatury {type}, która określa wpisywaćlisty.


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

Określ typy indeksów za pomocą {[indexType]: valueType} :


local numberList: {[string]: number} = {
Foo = 1,
Baz = 10
}
numberList["bar"] = true -- Type error: boolean can't convert to number

Tabele mogą również mieć wyraźne indeksy ciągów zdefiniowane w wpisywać.


type Car = {
Speed: number,
Drive: (Car) -> ()
}
local function drive(car)
-- Zawsze przestrzegaj ograniczenia prędkości
end
local taxi: Car = {Speed = 30, Drive = drive}

Wariatyki

Oto funkcja, która oblicza sumę dowolnej ilości liczb:


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

Jak oczekiwano, ta funkcja może przyjmować dowolną wartość, a sprawdzarka typów nie wyśle ostrzeżenia, jeśli podasz nieprawidłowy wpisywać, tak jak string.


print(addLotsOfNumbers(1, 2, 3, 4, 5)) -- 15
print(addLotsOfNumbers(1, 2, "car", 4, 5)) -- Attempt to add string to number

Zamiast tego przypisz typ do ..., tak jak przypisujesz dowolny inny wpisywać:


local function addLotsOfNumbers(...: number)

A teraz druga linia wywołuje błąd typu.


print(addLotsOfNumbers(1, 2, 3, 4, 5))
print(addLotsOfNumbers(1, 2, "car", 4, 5)) -- Błąd typu: ciąg nie mógł zostać przekonwertowany na liczbę

Jednak nie działa to, gdy piszesz definicję typu funkcjonalnego:


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

Zamiast tego użyj składnię ...type, aby określić wpisywaćwieloznaczny.


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

Związki i skrzyżowania

Możesz nawet zdefiniować typ jako dwa lub więcej typów za pomocą związku lub przecięcia:


type numberOrString = number | string
type type1 = {foo: string}
type type2 = {bar: number}
type type1and2 = type1 & type2 -- {foo: ciąg} & {bar: number}
local numString1: numberOrString = true -- Błąd typu
local numString2: type1and2 = {foo = "hello", bar = 1}

Określ wpisywaćwnioskowany

Możesz użyć funkcji typeof w definicji typu dla typów inferowanych:


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

Jednym ze sposobów korzystania z typeof jest zdefiniowanie typu metatable za pomocą setmetatable wewnątrz funkcji typeof:


type Vector = typeof(setmetatable({}::{
x: number,
y: number
}, {}::{
__add: (Vector, Vector|number) -> Vector
}))
-- Vector + Vector would return a Vector type

Generyki

Generyki są na podstawowym poziomie parametrów dla typów. Rozważ następujący obiekt State :


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

Bez generyków typ dla tego obiektu będzie następujący:


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

Jednak możesz chcieć, aby typ dla Value był oparty na otrzymanej wartości, co jest miejscem, w którym pojawiają się generyki:


type GenericType<T> = T

The <T> oznacza typ, który można ustawić na cokolwiek. Najlepszym sposobem wizualizacji tego jest jako wpisywaćzastępczy.


type List<T> = {T}
local Names: List<string> = {"Bob", "Dan", "Mary"} -- Typ staje się {ciąg}
local Fibonacci: List<number> = {1, 1, 2, 3, 5, 8, 13} -- Type becomes {number}

Generyki mogą również mieć wiele zastąpień wewnątrz nawiasów.


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

Aby ponownie przetworzyć obiekt State z wcześniejszego użycia ogólnego wpisywać:


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

Generyki funkcji

Funkcje mogą również używać generyków. Przykład State wywnioskuje wartość T z argumentów przychodzących funkcji.

Aby zdefiniować ogólną funkcję, dodaj <> do nazwy funkcji:


local function State<T>(key: string, value: T): State<T>
return {
Key = key,
Value = value
}
end
local Activated = State("Activated", false) -- Stan<bool>
local TimesClicked = State("TimesClicked", 0) -- State<number>

Eksportuj typy

Aby tak stało, typ może być używany poza ModuleScript , użyj kluczowa export :

Typ modułu w ReplicatedStorage

export type Cat = {
Name: string,
Meow: (Cat) -> ()
}
Skrypt korzystający z modułu typów

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()