lloyAlloy on GitHub
Attributes
Docs

Attributes

Attributes with checked placement

Updated

Built-in attributes drive codegen. Declared ones are metadata with typed arguments, and Attributes reads them at runtime. Completion after @ lists only what fits the position.

Alloyattributes.aly
1import { Serialize } from "@alloy/std/serde"
2
3attribute icon(asset: string) on struct, enum, variant
4attribute range(min: number, max: number) on field
5
6@icon("rbxassetid://100")
7@derive(Serialize)
8struct Item
9    @range(0, 99)
10    count: number
11end
Emitted Luausame line count
1local __alloy = require("@alloy")
2
3local icon = __alloy.attribute("icon", { "struct", "enum", "variant" }, { "asset" })
4local range = __alloy.attribute("range", { "field" }, { "min", "max" })
5
6local Item = {} Item.__index = Item
7
8
9
10
11 type Item = typeof(setmetatable({} :: { count: number }, Item)) setmetatable(Item, { __call = function(_, f: { count: number }): Item  return ((setmetatable(f, Item) :: any) :: Item) end }) function Item.new(f: { count: number }): Item return Item(f) end function Item.to_table(self) return { count = self.count } end function Item.serialize(self) return Item.to_table(self) end Item.__tostring = function(s) return __alloy.show_struct("Item", s, { "count" }) end __alloy.attrs(Item, { own = { icon = { "rbxassetid://100" } }, fields = { count = { range = { 0, 99 } } } }) return nil
  • Placement is checked: a wire width on a plain function parameter, or any attribute on a local, is a diagnostic and leaves the emit.
  • @test marks an inline test; @native, @checked, @deprecated, @inline, @noinline pass through to Luau.
  • Hover shows @icon(asset: string) and what it goes on, the same shape as the built-in ones.