# Lua Annotations for ESX (/docs/getting-started/annotations)

Annotations are special comments that tell the Lua language server (LuaLS, the "Lua" extension by sumneko) what types your functions take and return. Your editor then shows autocomplete, parameter hints and warnings, for example when you pass a string where a number is expected or forget to check a value that can be `nil`. They cost nothing at runtime: FiveM treats them as ordinary comments.

ESX Legacy itself is annotated, so with the right setup you get full autocomplete for `xPlayer`, accounts, jobs and items in your own scripts.

## Editor setup [#editor-setup]

1. Install [Lua by sumneko](https://marketplace.visualstudio.com/items?itemName=sumneko.lua) and [CfxLua IntelliSense](https://marketplace.visualstudio.com/items?itemName=overextended.cfxlua-vscode).
2. Point the language server at your copy of `es_extended` so it reads the ESX types:

```json title=".vscode/settings.json"
{
  "Lua.runtime.version": "Lua 5.4",
  "Lua.workspace.library": [
    "C:/FXServer/esx-server/resources/[core]/es_extended"
  ],
  "Lua.diagnostics.globals": ["ESX", "Config"]
}
```

Use the real path to your server's `es_extended` folder. On Linux or macOS use a normal Unix path.

## Annotation basics [#annotation-basics]

An annotation is a comment line that starts with `---` followed by a tag such as `@param`. It applies to the code directly below it.

| Tag | Purpose | Example |
| --- | --- | --- |
| `@param` | Type of a function parameter. Add `?` for optional. | `---@param amount number` |
| `@return` | Type of a return value, optionally with a name. | `---@return boolean success` |
| `@class` | Declares a table type. Can extend another class. | `---@class ShopItem` |
| `@field` | A field of a class. | `---@field price number` |
| `@type` | Type of a variable. | `---@type xPlayer?` |
| `@alias` | A name for a type or a set of literal values. | `---@alias Account 'money'\|'bank'` |
| `@cast` | Tell the server a variable has a narrower type from here on. | `---@cast xPlayer xPlayer` |
| `@deprecated` | Marks a function as deprecated; callers get a strikethrough. | `---@deprecated` |
| `@diagnostic` | Disable a warning for a line or file. | `---@diagnostic disable-next-line: undefined-global` |

Common types: `string`, `number`, `integer`, `boolean`, `table`, `function`, `nil`, `any`, arrays like `string[]`, maps like `table<string, number>`, unions like `string|number`, and FiveM's `vector3`.

## Documenting a function [#documenting-a-function]

```lua title="server/utils.lua"
--- Pays a player from a society account.
--- Returns false when the player is not loaded or the amount is invalid.
---@param playerId number Server ID of the player
---@param amount integer Amount in dollars, must be positive
---@param reason? string Shown in logs, defaults to "Payment"
---@return boolean success
local function payPlayer(playerId, amount, reason)
    if amount <= 0 then return false end

    local xPlayer = ESX.GetPlayerFromId(playerId)
    if not xPlayer then return false end

    xPlayer.addAccountMoney('bank', amount, reason or 'Payment')
    return true
end
```

Now hovering `payPlayer` shows the description, and calling `payPlayer('1', 500)` gets a warning because `'1'` is a string.

## Using the ESX types [#using-the-esx-types]

`es_extended` defines these classes in `server/classes/player.lua`:

| Class | Describes |
| --- | --- |
| `xPlayer` | The full server-side player object (extends `StaticPlayer`) |
| `StaticPlayer` | The method interface of a player |
| `ESXAccount` | An account: `name`, `money`, `label`, `round`, `index` |
| `ESXJob` | A job: `name`, `label`, `grade`, `grade_name`, `grade_label`, `grade_salary`, `onDuty`, ... |
| `ESXItem`, `ESXInventoryItem` | An item and an item with `count` |
| `ESXInventoryWeapon` | A weapon in the loadout with `ammo`, `components`, `tintIndex` |

Use them in your own annotations:

```lua title="server/main.lua"
---@param xPlayer xPlayer
---@return boolean
local function isOnDutyPolice(xPlayer)
    local job = xPlayer.job ---@type ESXJob
    return job.name == 'police' and job.onDuty == true
end

RegisterNetEvent('my_police:action', function()
    local xPlayer = ESX.GetPlayerFromId(source) ---@type xPlayer?
    if not xPlayer then return end

    if isOnDutyPolice(xPlayer) then
        -- autocomplete works here: xPlayer.getAccount, xPlayer.showNotification, ...
    end
end)
```

Marking the variable as `xPlayer?` (nullable) makes the language server warn you if you use it before the `nil` check, which is exactly the bug that causes most `attempt to index a nil value` errors.

## Declaring your own classes [#declaring-your-own-classes]

Describe the shape of your config or data tables once and get checks everywhere you use them.

```lua title="config.lua"
---@class ShopItem
---@field name string Item name from the items table
---@field label string
---@field price integer

---@class ShopConfig
---@field coords vector3
---@field items ShopItem[]

---@type ShopConfig
Config = {
    coords = vector3(25.7, -1347.3, 29.5),
    items = {
        { name = 'water', label = 'Water', price = 25 },
        { name = 'bread', label = 'Bread', price = 15 },
    },
}
```

A typo like `prcie = 15` now shows a warning instead of a silent `nil` at runtime.

### Aliases for fixed values [#aliases-for-fixed-values]

```lua
---@alias NotifyType 'info'|'success'|'error'

---@param message string
---@param notifyType? NotifyType
local function notify(message, notifyType)
    ESX.ShowNotification(message, notifyType or 'info')
end
```

The editor now suggests only the three valid notification types.

## Tips [#tips]

- Annotate public functions and config tables first. That is where most type mistakes happen.
- Keep descriptions short. One line about *what* and anything surprising about *when* it returns `nil`.
- Do not disable diagnostics for a whole workspace to silence one warning. Use `---@diagnostic disable-next-line` where needed.
- The full annotation reference is in the [LuaLS wiki](https://luals.github.io/wiki/annotations/).

## Related [#related]

- [Coding practices](/docs/getting-started/coding-practices)
- [Development tools](/docs/getting-started/tools)
- [xPlayer reference](/docs/es_extended/server/xplayer)
