– Struct.Luau
local function deepClone(t)
local copy = {}
for k, v in pairs(t) do
if type(v) == “table” then
copy[k] = deepClone(v) – Ensure deep copying of tables
else
copy[k] = v
end
end
return copy
end
return function(fields: T)
return function(…): T
local struct = deepClone(fields) – Copy fields as base
local args = {…}
local def = args[1]
-- If a constructor exists, call it
if struct.constructor then
struct:constructor(...)
elseif def then
for k, v in pairs(def) do
struct[k] = v
end
end
-- Mixin behavior
local traits = struct.use
if traits then
for _, trait in ipairs(traits) do
for k, v in pairs(deepClone(trait)) do -- Clone to prevent shared state issues
if struct[k] == nil then
struct[k] = v
end
end
end
end
-- Inheritance handling
local inheritfrom = struct.super and deepClone(struct.super) or {}
for k, v in pairs(inheritfrom) do
if struct[k] == nil then
struct[k] = v
end
end
-- Make struct immutable to prevent accidental changes
return setmetatable({}, {
__index = struct,
})
end, fields
end
– Simple.luau
–!strict
local Struct = require(game.ServerScriptService.Struct)
– Movable Trait
local Movable = {
x = 0;
y = 0;
move = function(self: Movable, x: number, y: number)
self.x = self.x + x
self.y = self.y + y
print("Object moved to (" .. tostring(self.x) .. ", " .. tostring(self.y) .. ")")
end,
moveto = function(self: Movable, x: number, y: number)
self:move(x, y)
end,
}
– Attackable Trait
local Attackable = {
name = “”;
attack = function(self: Attackable, target: {name: string})
print(self.name .. " attacks " .. tostring(target.name) .. "!")
end,
}
– Entaty to Test
local Entity = Struct{
use = { Movable, Attackable },
name = "Unknown",
x = 0,
y = 0,
move = function(self: Entity, x: number, y: number)
self.x = self.x + x
self.y = self.y + y
print(self.name .. " moved to (" .. tostring(self.x) .. ", " .. tostring(self.y) .. ")")
end,
}
– Main Execution
if true then
local player: Entity= Entity{
name = “Hero”,
x = 10,
y = 5
}:: Entity
player:move(5, -3)
player:attack{ name = "Goblin" }
player:moveto(-10, 8)
end
– Object Type
type Movable = typeof(Movable)
type Attackable = typeof(Attackable)
type Entity = typeof(Entity()) & Attackable & Movable
I am trying to create a system of encapsulation, for a struct but the type system is not reutrning key important areas. specificaly no return values for inherited behavior through the mixin system or the super system. I am also looking into having the system also look for _[field] to remove them from the interface. Finaly I want to remove the super and use fields from the struct interface.
I think type functions could solve this but I am having issues with it. So if anyone can help it would be greatly appreciate.
My goal
– Main Execution
if true then
local player: Entity= Entity{
name = “Hero”,
x = 10,
y = 5
}
player:move(5, -3)
player:attack{ name = "Goblin" }
player:moveto(-10, 8)
end
– Object Type
type Movable = typeof(Movable)
type Attackable = typeof(Attackable)
type Entity = typeof(Entity())
Without erroring.