Verificação de Tipo

*Este conteúdo é traduzido por IA (Beta) e pode conter erros. Para ver a página em inglês, clique aqui.

O Luau suporta um tipo de sistema gradual através do uso de anotações de tipo e inferência de tipo. Esses tipos são usados para fornecer avisos, erros e sugestões melhores no Editor de Scripts.

Definindo um Tipo

Use a palavra-chave type para definir seus próprios tipos:


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

Modos de Inferência

Existem três modos de inferência de tipo Luau que podem ser configurados na primeira linha de um Script :

  • --!nocheck - Não verifique os tipos
  • --!nonstrict - Modo padrão para todos os scripts, apenas afirma tipos variáveis se forem explicitamente anotados
  • --!strict - Afirma todos os tipos com base no digitarimplicado ou explicitamente anotado

O modo padrão para o tipo checker é --!nonstrict. Os dois outros modos controlam o quão rígido o tipo checker é com inferir e verificar tipos para variáveis e funções. Qualquer tipo de desacordo em scripts são destacados no Editor de Scripts e na superfície como avisos no Análise de Scripts janela.

Tipos

Uma anotação de tipo pode ser definida usando o operador : , seguido por uma definição de tipo. Por padrão, no modo nonstrict, todos os tipos são atribuídos ao tipo any.


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

Existem quatro tipos primitivos que podem ser usados em uma anotação:

  • nil - sem valor
  • boolean - true ou false
  • number - um valor numérico
  • string - texto

Dentro do Roblox, todas as Classes, tipos de dados e enums têm seus próprios tipos que você pode verificar contra:


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

Para tornar um tipo opcional, use um ? no final da anotação:


local foo: string? = nil

Isso permitirá que a variável seja o tipo especificado (neste caso string ) ou nil .

Tipos Líticos

Você também pode usar string e boolean em vez de usar string / cadeia / texto e 1>button1> :


local alwaysHelloWorld: "Hello world!" = "Hello world!"
alwaysHelloWorld = "Just hello!" -- Tipo de erro: o tipo "Olá!" não pode ser convertido em "Olá mundo!"
local alwaysTrue: true = false -- Type error: Type 'false' could not be converted into 'true'

Tipos de Casts

Às vezes, você pode precisar ajudar o tipoChecker ao explicar um valor para um diferente tipo com o operador :::


local myNumber = 1
local myString: string
myString = myNumber -- Não está tudo bem; digite o erro de conversão
myString = myNumber :: any -- OK; todas as expressões podem ser convertidas em 'qualquer'
local myFlag = myNumber :: boolean -- Not OK; types are unrelated

Tipo de Função

Considerar a seguinte função:


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

Essa função adiciona x a y, mas erros se um ou ambos são uma string / cadeia / texto. Luau não sabe que essa função só pode usar números. Para evitar essa categoria de problema, adicione tipos aos parâmetros:


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

O Luau agora sabe que a função leva dois números e lança um aviso se você tentar passar qualquer coisa que não seja um número para a função:


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

Para definir um digitarde retorno, coloque um operador : no final da definição da função:


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

Para retornar múltiplos tipos, coloque os tipos em paises:


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

Definindo um Tipo Funcional

Um tipo funcional pode ser definido usando a sintaxe (in) -> out. Usando as funções dos exemplos anteriores, os tipos das funções são:


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

Tipos de Tabela

O Luau não tem um digitarde tabela; em vez disso, os tipos de tabela são definidos usando a sintaxe table. Uma maneira de definir tabelas é usar a sintaxe {}, que define um digitarde lista.


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

Defina os tipos de índice usando {[indexType]: valueType} :


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

As tabelas também podem ter índices de string explícitos definidos em um digitar.


type Car = {
Speed: number,
Drive: (Car) -> ()
}
local function drive(car)
-- Sempre vá para o limite de velocidade
end
local taxi: Car = {Speed = 30, Drive = drive}

Variáveis

Aqui está uma função que calcula a soma de um número aleatório de números:


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

Como esperado, esta função pode levar qualquer valor, e o tipochecker não irá mostrar uma mensagem de aviso se você fornecer um digitarinválido, como uma string.


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

Em vez disso, atribua um tipo ao ..., assim como você atribui qualquer outro digitar:


local function addLotsOfNumbers(...: number)

E agora, a segunda linha erra um erro de tipo.


print(addLotsOfNumbers(1, 2, 3, 4, 5))
print(addLotsOfNumbers(1, 2, "car", 4, 5)) -- Tipo de erro: string não pode ser convertido em número

No entanto, isso não funciona ao escrever uma definição de tipo funcional:


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

Em vez disso, use a sintaxe ...type para definir um digitarvariado.


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

Uniões e Interseções

Você pode até mesmo definir um tipo como dois ou mais tipos usando uma união ou interseção:


type numberOrString = number | string
type type1 = {foo: string}
type type2 = {bar: number}
type type1and2 = type1 & type2 -- :{foo: string / cadeia / texto} & {bar: number}
local numString1: numberOrString = true -- Tipo de erro
local numString2: type1and2 = {foo = "hello", bar = 1}

Definindo um Tipo Implicado

Você pode usar a função typeof em uma definição de tipo para tipos implícitos:


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

Um modo de usar typeof é definir um tipo de metabela usando setmetatable dentro da função typeof:


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

Gerais

Genéricos são parâmetros de nível básico para tipos. Considere o seguinte ObjetoState:


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

Sem genéricos, o tipo para este objeto seria o seguinte:


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

No entanto, você pode querer que o tipo para Value seja baseado no valor recebido, onde os genéricos vêm em:


type GenericType<T> = T

O <T> denota um tipo que pode ser definido para qualquer coisa. A melhor maneira de visualizar isso é como um digitarde substituição.


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

Genéricos também podem ter várias substituições dentro dos parênteses.


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

Para reworkar o objeto State de antes para usar um digitargenérico:


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

Gericos de Função

Funções também podem usar genéricos. O exemplo State infere o valor de T dos argumentos recebidos da função.

Para definir uma função genérica, adicione um <> ao nome da função:


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

Tipos de Exportação

Para que um tipo possa ser usado fora de um ModuleScript, use a palavra-chave export:

Tipos de Módulo em ReplicatedStorage

export type Cat = {
Name: string,
Meow: (Cat) -> ()
}
Script Usando o Módulo de Tipos

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