Overview
@class defines a named type that other annotations can use. Classes support inheritance, generic type parameters, access control, and field definitions.
Syntax
---@class ClassName
---@class ClassName : ParentClass
---@class ClassName : Parent1, Parent2
---@class (exact) ClassName
---@class (partial) ClassName
---@class ClassName<T>
Basic class
---@class Animal
---@field name string Animal name
---@field species string Species
local Animal = {}
function Animal:Speak()
print(self.name .. " makes a sound")
end
Inheritance
Use : ParentClass to extend another class. The child class gets the parent’s fields and methods.
---@class Dog : Animal
---@field breed string Dog breed
local Dog = setmetatable({}, { __index = Animal })
function Dog:Fetch(item)
-- inherits Animal fields: self.name, self.species ✅
end
Multiple inheritance
---@class Flyable
---@field maxAltitude number
---@class Swimmable
---@field maxDepth number
---@class Duck : Animal, Flyable, Swimmable
---@field featherColor string
Exact classes
Mark a class as (exact) to prevent dynamic field additions. GLuaLS can report a diagnostic when code assigns a field outside the class definition:
In GLuaLS, this annotation has no effect. GLuaLS treats all classes as partial by default and turns related diagnostics off. GLuaLS keeps it for EmmyLua compatibility.
---@class (exact) Point
---@field x number
---@field y number
local p = Point.new(1, 2)
p.z = 3 -- ❌ Error: cannot add field 'z' to exact type Point
Partial classes
(partial) extends an existing class without relisting all fields:
In GLuaLS, this annotation has no effect. GLuaLS treats all classes as partial by default and turns related diagnostics off. GLuaLS keeps it for EmmyLua compatibility.
-- In one file:
---@class Animal
---@field name string
-- In another file:
---@class (partial) Animal
---@field weight number -- adds weight to Animal without losing name
Generic classes
Add type parameters with angle brackets. You can use type parameters in field types:
---@class Container<T>
---@field items T[]
---@field capacity number
---@type Container<string>
local stringContainer = { items = {}, capacity = 10 }
stringContainer.items[1] = "hello" -- ✅ typed as string
Field access control
Use access modifiers in @field:
Access modifiers are optional. They affect type checking only, not runtime behavior. GLuaLS checks them and can report diagnostics when code uses private or protected fields from the wrong place.
---@class MyClass
---@field public name string Accessible everywhere
---@field private m_id number Only accessible in class methods
---@field protected m_parent MyClass Accessible in subclasses
See @field for details.
Attaching a class to a local variable
When you place ---@class above a local statement, GLuaLS types that variable as an instance of the class:
---@class Player
local Player = {}
-- Player is now typed as "instance of Player class"
To type a constructor table instead, use @type:
local Player = {}
---@type Player
local ply = Player.new()