Skip to main content

Overview

@generic adds type parameters to a function. GLuaLS uses them to carry types through helpers such as filter, map, and wrapper functions.

Syntax

---@generic T
---@generic T : ConstraintType
---@generic T, U, V

Basic generic function

---@generic T
---@param value T
---@return T
function identity(value)
    return value
end

local x = identity("hello")  -- x is inferred as string
local y = identity(42)       -- y is inferred as number

Multiple type parameters

---@generic K, V
---@param map table<K, V>
---@return K[]
function getKeys(map)
    local keys = {}
    for k in pairs(map) do keys[#keys+1] = k end
    return keys
end

Generic with constraint

Use : ConstraintType to restrict the types that T accepts:
---@generic T : Entity
---@param ent T
---@return T
function CloneEntity(ent)
    -- T must be Entity or a subtype (Player, NPC, etc.)
end

Generic arrays

---@generic T
---@param items T[]
---@param predicate fun(item: T): boolean
---@return T[]
function filter(items, predicate)
    local result = {}
    for _, item in ipairs(items) do
        if predicate(item) then result[#result+1] = item end
    end
    return result
end

local players = filter(player.GetAll(), function(ply) return ply:IsAdmin() end)
-- players is typed as Player[]

When to use generics

Generics work best for:
  • Functions that transform a value but keep its type
  • Functions that filter or map over a typed list
  • Functions that take a callback and return its result type
For simple cases, a union type or any can be easier to read.

String-template capture (GLuaLS)

Use backticks when a string argument names a class or type. Use this when a function takes a class name as text and returns that class type:
---@class Entity
---@class sent_npc : Entity

---@generic T : Entity
---@param class `T`
---@return T
function ents.Create(class) end

local ent = ents.Create("sent_npc") -- inferred as sent_npc
For collection-returning functions:
---@generic T : Entity
---@param class `T`
---@return T[]
function ents.FindByClass(class) end
Rule:
  • T uses the normal Lua value type ("x" becomes string)
  • `T` uses the string text as a class or type name ("sent_npc" becomes sent_npc)
Common string-template forms:
---@class aaa.`T`.bbb
---@class aaa.`T`
---@class `T`.bbb
---@class `T`

Explicit generic call arguments

When inference is unclear, pass generics at the call site:
---@overload fun<T>(value: T): T
local function callGeneric(value)
    return value
end

local forced = callGeneric--[[@<number | string>]](1)