Typüberprü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 schrittweises Typsystem durch die Verwendung von Typannotationen und Typinferenz. Diese Typen werden verwendet, um bessere Warnungen, Fehler und Vorschläge im Skript-Editor bereitzustellen.

Definiere einen Typ

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


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

Inferenzmodi

Es gibt drei Luau-Typinferenzmodi, die in der ersten Zeile eines Script festgelegt werden können:

  • --!nocheck — Überprüfe keine Typen.
  • --!nonstrict — Stellt nur sicher, dass Variablentypen angegeben werden, wenn sie explizit annotiert sind.
  • --!strict — Stellt alle Typen basierend auf dem inferierten oder explizit annotierten Typ sicher.

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

Um einen Standardmodus für alle Skripte festzulegen, den du nach Bedarf überschreiben kannst, siehe Workspace.LuauTypeCheckMode.

Typen

Eine Typannotation kann unter Verwendung des :-Operators nach einer lokalen Variable definiert werden, gefolgt von einer Typdefinition. Standardmäßig wird im nonstrict-Modus allen Variablen der Typ any zugewiesen.


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

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

  • nil - kein Wert
  • boolean - true oder false
  • number - ein numerischer Wert
  • string - Text

Innerhalb von Roblox haben alle Klassen, Datentypen und Enums ihre eigenen Typen, gegen die du überprüfen kannst:


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 Annotation:


local foo: string? = nil

Dies erlaubt es der Variablen, entweder den angegebenen Typ (in diesem Fall string) oder nil zu sein.

Literale Typen

Du kannst auch Zeichenfolgen und Booleans in literale Werte umwandeln, anstatt string und boolean zu verwenden:


local alwaysHelloWorld: "Hello world!" = "Hello world!"
alwaysHelloWorld = "Just hello!" -- Typfehler: Typ '"Just hello!"' konnte nicht in '"Hello world!"' umgewandelt werden
local alwaysTrue: true = false -- Typfehler: Typ 'false' konnte nicht in 'true' umgewandelt werden

Typumwandlungen

Manchmal musst du den Typprüfer unterstützen, indem du einen Wert mit dem ::-Operator explizit in einen anderen Typ umwandelst:


local myNumber = 1
local myString: string
myString = myNumber -- Nicht OK; Typumwandlungsfehler
myString = myNumber :: any -- OK; alle Ausdrücke können in 'any' umgewandelt werden
local myFlag = myNumber :: boolean -- Nicht OK; Typen sind nicht verwandt

Funktionstypen

Betrachte die folgende Funktion:


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

Diese Funktion addiert x zu y, gibt jedoch einen Fehler zurück, wenn einer oder beide davon eine Zeichenfolge sind. Luau weiß nicht, dass diese Funktion nur Zahlen verwenden kann. Um diese Art von Problem zu verhindern, füge Typen zu den Parametern hinzu:


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

Luau weiß nun, dass die Funktion zwei Zahlen erwartet, und gibt eine Warnung aus, wenn du versuchst, etwas, das keine Zahl ist, in die Funktion zu übergeben:


add(5, 10)
add(5, "foo") -- Typfehler: Zeichenfolge konnte nicht in Zahl umgewandelt werden

Um einen Rückgabewert zu definieren, setze einen :-Operator am Ende der Funktionsdefinition:


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

Um mehrere Typen zurückzugeben, setze die Typen in Klammern:


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

Definiere einen funktionalen Typ

Ein funktionaler Typ kann mit der Syntax (in) -> out definiert werden. Unter Verwendung der Funktionen aus den vorherigen Beispielen lauten die Typen der Funktionen:


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

Tabellentypen

Luau hat keinen table-Typ; stattdessen werden Tabellentypen mit der {}-Syntax definiert. Eine Möglichkeit, Tabellen zu definieren, besteht darin, die {type}-Syntax zu verwenden, die einen Listentyp definiert.


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

Definiere Indextypen mit {[indexType]: valueType}:


local numberList: {[string]: number} = {
Foo = 1,
Baz = 10
}
numberList["bar"] = true -- Typfehler: boolean kann nicht in Zahl umgewandelt werden

Tabellen können auch explizite Zeichenfolgenindizes in einem Typ definiert haben.


type Car = {
Speed: number,
Drive: (Car) -> ()
}
local function drive(car)
-- Immer die Geschwindigkeitsgrenze einhalten
end
local taxi: Car = {Speed = 30, Drive = drive}

Variadische Argumente

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 gibt keine Warnung aus, wenn du einen ungültigen Typ (wie eine string) bereitstellst.


print(addLotsOfNumbers(1, 2, 3, 4, 5)) -- 15
print(addLotsOfNumbers(1, 2, "car", 4, 5)) -- Versuch, einen String zu einer Zahl hinzuzufügen

Stattdessen weise dem ... einen Typ zu, genau wie du jedem anderen Typ eine Zuweisung machst:


local function addLotsOfNumbers(...: number)

Und jetzt wird die zweite Zeile einen Typfehler auslösen.


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

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


type addLotsOfNumbers = (...: number) -> number -- Erwarteter Typ, erhalten: ':'

Verwende stattdessen die Syntax ...type, um einen variadischen Typ zu definieren.


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

Vereinigungen und Schnittmengen

Du kannst sogar einen Typ als zwei oder mehr Typen mithilfe einer Vereinigung oder Schnittmenge definieren:


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

Definiere einen inferierten Typ

Du kannst die Funktion typeof in einer Typdefinition für inferierte Typen verwenden:


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

Eine Möglichkeit, typeof zu verwenden, besteht darin, einen Metatyp mithilfe von setmetatable innerhalb der typeof-Funktion zu definieren:


type Vector = typeof(setmetatable({}::{
x: number,
y: number
}, {}::{
__add: (Vector, Vector|number) -> Vector
}))
-- Vector + Vector würde einen Vektor-Typ zurückgeben

Generika

Generika sind auf einer grundlegenden Ebene Parameter für Typen. Betrachte das folgende State-Objekt:


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

Ohne Generika würde der Typ für dieses Objekt wie folgt aussehen:


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

Wenn du jedoch möchtest, dass der Typ für Value auf dem eingehenden Wert basiert, kommt hier die Generik ins Spiel:


type GenericType<T> = T

Das <T> bezeichnet einen Typ, der auf alles gesetzt werden kann. Am besten kann man sich das als einen Substitutionstyp vorstellen.


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

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


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

Um das State-Objekt von früher so umzuarbeiten, dass es einen generischen Typ verwendet:


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

Funktionsgenerika

Funktionen können auch Generika verwenden. Das State-Beispiel leitet den Wert von T von den eingehenden Argumenten der Funktion ab.

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


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>

Typ-Exports

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

Typenmodul in ReplicatedStorage

export type Cat = {
Name: string,
Meow: (Cat) -> ()
}
Skript, das das Typenmodul verwendet

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Types = require(ReplicatedStorage.Types)
local newCat: Types.Cat = {
Name = "metatablecat",
Meow = function(self)
print(`{self.Name} sagte miau`)
end
}
newCat:Meow()
©2026 Roblox Corporation. Roblox, das Roblox-Logo und "Powering Imagination" gehören zu unseren eingetragenen und nicht eingetragenen Markenzeichen in den USA und anderen Ländern.