Typprüfung

*Dieser Inhalt wurde mit KI (Beta) übersetzt und kann Fehler enthalten. Um diese Seite auf Englisch zu sehen, klicke hier.

Luau unterstützt ein graduelles Typensystem durch die Verwendung von Typ-Annotations und Typ-Behauptungen.Diese Arten werden verwendet, um bessere Warnungen, Fehler und Vorschläge im Skript-Editor bereitzustellen.

Definieren Sie einen eingeben

Verwende das type-Schlüsselwort, um deine eigenen Arten zu definieren:


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

Schlussfolgerungsmodi

Es gibt drei Luau-Typ-Inferenzmodi, die auf der ersten Zeile eines Script festgelegt werden können:

  • --!nocheck — Überprüfe keine Arten.
  • --!nonstrict — Behauptet nur Variantentypen, wenn sie explizit angezeichnet sind.
  • --!strict — Behauptet alle Arten basierend auf dem abgeleiteten oder explizit angegebenen eingeben.

Die --!nonstrict- und --!strict-Modi steuern, wie streng der Typenprüfer bei der Inferenz und Überprüfung von Typen für Variablen und Funktionen ist.Alle Arten von Fehlern in Skripten werden im Skript-Editor hervorgehoben und als Warnungen im Skript-Analyse-Fenster angezeigt.

Arten

Eine Typ-Annotation kann mit dem Operator : nach einer lokalen Variable definiert werden, gefolgt von einer Typ-Definition.Standardmäßig, im Modus nonstrict , werden alle Variablen dem Typ any zugewiesen.


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

Es gibt vier primitive Arten, die in einer Annotation verwendet werden können:

  • nil - kein wert
  • boolean - true or false
  • number - ein numerischer wert
  • string - text

Innerhalb von Roblox haben alle Klassen, Datenformate und Enums eigene Arten, gegen die Sie überprüfen können:


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

Um einen Typ optional zu machen, verwende ein ? am Ende der Anmerkung:


local foo: string? = nil

Dies wird es der Variable ermöglichen, entweder der angegebenen Art zu sein (in diesem Fall string ) oder nil .

Literal-Typen

Du kannst auch Zeichenketten und Booleen zu literalen Werten ausgeben, anstatt string und boolean zu verwenden:


local alwaysHelloWorld: "Hello world!" = "Hello world!"
alwaysHelloWorld = "Just hello!" -- Fehlertyp: Der Fehlertyp 'Just hello!' konnte nicht in 'Hallo Welt!' umgewandelt werden
local alwaysTrue: true = false -- Type error: Type 'false' could not be converted into 'true'

Typ-Castings

Manchmal müssen Sie den Typprüfer möglicherweise unterstützen, indem Sie einen Wert explizit auf einen anderen Typ mit dem :: Operator kastrieren:


local myNumber = 1
local myString: string
myString = myNumber -- Nicht in Ordnung; Art der Umwandlungsfehler eingeben
myString = myNumber :: any -- OK; alle Ausdrücke können auf 'any' gecastet werden
local myFlag = myNumber :: boolean -- Not OK; types are unrelated

Funktionentypisierung

Betrachte die folgende Funktion:


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

Diese Funktion fügt x zu y hinzu, aber Fehler, wenn einer oder beide sind eine String.Luau weiß nicht, dass diese Funktion nur Zahlen verwenden kann.Um diese Kategorie von Problemen zu verhindern, füge Arten zu den Parametern hinzu:


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

Luau weiß jetzt, dass die Funktion zwei Zahlen verwendet und eine Warnung ausgibt, wenn du versuchst, irgendetwas, das keine Zahl ist, in die Funktion zu übergeben:


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

Um einen eingebenzu definieren, stelle einen : -Operator am Ende der Funktions definition ein:


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

Um mehrere Arten zurückzugeben, stelle die Arten in Klammern dar:


local function FindSource(script: BaseScript, pattern: string): (string, number)
return 42, true -- Fehler eingeben
end

Definiere einen funktionalen eingeben

Ein funktionaler Typ kann durch die Syntax (in) -> out definiert werden. Mit den Funktionen aus den vorherigen Beispielen sind die Arten der Funktionen:


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

Tabellenarten

Luau hat keinen table eingeben; stattdessen werden Tabellenarten mit {} Syntax definiert.Eine Möglichkeit, Tabellen zu definieren, ist die Verwendung der {type}-Syntax, die einen Listen eingebendefiniert.


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

Definieren Sie Indexarten mit {[indexType]: valueType} :


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

Tabellen können auch explizite Zeichenindizes haben, die in einem eingebendefiniert sind.


type Car = {
Speed: number,
Drive: (Car) -> ()
}
local function drive(car)
-- Gehen Sie immer das Geschwindigkeitslimit
end
local taxi: Car = {Speed = 30, Drive = drive}

Variatiken

Hier ist eine Funktion, die die Summe einer beliebigen Anzahl von Zahlen berechnet:


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

Wie erwartet, kann diese Funktion jeden Wert annehmen, und der Typprüfer wird keine Warnung auslösen, wenn du einen ungültigen eingebenlieferst, wie z. B. string.


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

Stattdessen weise einen Typ auf die ... zu, genau wie du einen anderen eingebenzuordnest:


local function addLotsOfNumbers(...: number)

Und jetzt erhebt die zweite Zeile einen Typfehler.


print(addLotsOfNumbers(1, 2, 3, 4, 5))
print(addLotsOfNumbers(1, 2, "car", 4, 5)) -- Fehlertyp: Zeichenkette konnte nicht in Zahl umgewandelt werden

Dies funktioniert jedoch nicht, wenn du eine funktionale Typdefinition schreibst:


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

Verwende stattdessen die Syntax ...type, um einen variablen eingebenzu definieren.


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

Verbindungen und Kreuzungen

Du kannst sogar einen Typ definieren, als zwei oder mehrere Arten mit einer Union oder Intersektion:


type numberOrString = number | string
type type1 = {foo: string}
type type2 = {bar: number}
type type1and2 = type1 & type2 -- {foo: string} & {bar: number}
local numString1: numberOrString = true -- Fehlertyp
local numString2: type1and2 = {foo = "hello", bar = 1}

Definieren Sie einen abgeleiteten eingeben

Du kannst die typeof-Funktion in einer Typdefinition für abgeleitete Arten verwenden:


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

Eine Möglichkeit, typeof zu verwenden, besteht darin, einen metastierbaren Typ mit setmetatable innerhalb der typeof-Funktion zu definieren:


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

Generische

Generika sind auf einer grundlegenden Ebene-Paramètres für Arten. Betrachten Sie das folgende State Objekt:


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

Ohne Generics wäre der Typ für dieses Objekt wie folgt:


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

Sie möchten jedoch, dass der Typ für Value auf den eingehenden Wert basiert, wo Generatoren ins Spiel kommen:


type GenericType<T> = T

Die <T> zeigt einen Typ an, der auf alles gesetzt werden kann. Die beste Art, dies visuell darzustellen, ist als eingeben.


type List<T> = {T}
local Names: List<string> = {"Bob", "Dan", "Mary"} -- Typ wird zu {String}
local Fibonacci: List<number> = {1, 1, 2, 3, 5, 8, 13} -- Type becomes {number}

Generika können auch mehrere Substitutionen innerhalb der Klammern haben.


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

Um das State Objekt von früher neu zu verwenden, um einen generischen eingebenzu verwenden:


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

Funktionsgenerika

Funktionen können auch Generika verwenden. Das State Beispiel schließt den Wert von T aus den eingehenden Argumenten der Funktion ab.

Um eine generische Funktion zu definieren, füge ein <> zum Funktionsnamen hinzu:


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

Typ-Ausgaben

Um das so zu machen, dass ein Typ außerhalb einer ModuleScript verwendet werden kann, verwende das Schlüsselwort export:

Typenmodul in ReplicatedStorage

export type Cat = {
Name: string,
Meow: (Cat) -> ()
}
Skript mit dem Typenmodul verwenden

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