I want luau typechecking for my networking module to function correctly- it has an initialize function that gets passed a table, and that table is then deep-copied by a function, into each new piece of data that the module creates.
My question, is how can I copy the original initialize table’s typechecking autofill stuff, to work on all tables I deep copy it from? Is there some way I can do something like
local DefaultTable = InitializeInitializeCallResult -- The table sent at runtime by an Initialize function call. I am willing to change this setup though, if it's necessary
type DefaultTableType = DefaultTable.Type
-- later when the data is being made
local NewData: DefaultTableType = DeepCopy(DefaultTable) -- DeepCopy does some special stuff in how it handles recursive tables
and have something like that just copy-paste whatever typechecking? In my example, DefaultTable can be a different value everu project, and I’d like to not have to manually make a type to mimic that table if possible.
local defaultTable = require(someModule)
local newData: typeof(someTable) = deepCopy(defaultTable)
Or you can explicitly return the generic type of the argument passed:
--!strict
local function deepCopy<T>(t: T): T
t = table.clone(t :: any) :: any -- ignore type check for t and table.clone
for index: any, value: any in t :: any do -- ignore type check for table iteration
if typeof(value) == "table" then
(t :: any)[index] = deepCopy(value) -- ignore type check for table indexing
end
end
return t
end
local a = deepCopy({key1 = true}) -- intellisense of t argument
If there are dynamic keys being added and/or the variable is not statically typed, then no it is not possible. You can kinda merge table types by doing something like
local newData: typeof(someTable) & typeof(anotherTable) = someMergingOperation()
Typof can be used to “copy” whatever type a table has? And it’s a “static” table in the sense that it’s from a function that’s only ever called once… but if it won’t work for a function, I’m game for moving it over to be a table property you assign in the module.
Sounds like it might be what I wanted, gonna test it out tonight.
Not sure if you still need this, but for anyone looking the future I made this function that satisfies strict type checking and works with autocomplete on the deep copied table:
--Deep copies and returns a new table, where changes do not affect the original table
@native function TableLibrary.deepCopy<T>(CloneThis:T&{}) : T
assert(type(CloneThis) == `table`, `You can only deep copy tables!`)
local MetaTable = getmetatable(CloneThis)
local NewTable = (if MetaTable then setmetatable({}, MetaTable :: {}?) else {}) :: typeof(CloneThis)
for i, v in CloneThis do
if type(v) == `table` then
NewTable[i] = TableLibrary.deepCopy(v)
else
NewTable[i] = v
end
end
return NewTable
end
It should be compatible with metatables and functions as well so if you need to deep copy a custom object (in OOP or similar), it should work well. I chose not to use table.clone() because it would create new functions instead of references to the old functions if they are present in the original table, which isn’t necessary and would likely cause memory issues.