Metatables inherently isn’t a value type, they’re just normal tables assigned to another table to give functionality so I don’t think they would add such
although a solution if you really need to
type func = type(function() end)
type metatable = {
__index : func | {any},
__newindex : func : {any},
__call : func,
__tostring : func,
__metatable : string,
__mode : string
}
local function getmetatable(...) : metatable?
return getmetatable(...)
end
can you explain the logical thought process of the computer when you tell it to do something using “::” (assertion) because while i can understand the other type operator on a basic level, the way you explained it using “this works” “this does not work” formula for assertion had me on the ropes
Great tutorial!
I knew a little about type setting but couldn’t figure out how to define types within Tables for a long time, great lesson. Thank you very much!
Only problem I have is how would I get these types globally recognized by server and client scripts?
I found out one of the ways via the Luau documentation (export keyword)
I managed to use this post, coolalex1835’s + 7z99’s reply and the Luau documentation OP linked to construct a rudimentary custom type called “Command” based off of CMDR. It’s a bit confusing to learn this stuff though.
Custom Type - Command
Type Definition Script (ServerScriptService → ModuleScript)
-- Type Definitions
-- Export this type with the Module Script so that we can access it. Not *necessary* but useful just in case
export type executable = (player : Player | nil, args : {string}) -> boolean
export type command = {
Name : string,
HasMetatableAccess : boolean | nil,
Exec : executable,
metatable : {any} | nil
} | nil
-- Type Constructors
local Command = {}
Command.New = function(name : string, metatableAccess : boolean, Exec : executable, metatable : {} | nil) : command
local c : command = {}
c.Name = name
c.HasMetatableAccess = metatableAccess
c.Exec = Exec
c.metatable = metatable
return c
end
return Command
Example Command using the Type Definition:
-- Require the Command Definition
local c = require(script.Parent.Command)
-- Create an Execute Function (that follows the Executable type)
function Execute(p : Player | nil, args : {string} | nil) : boolean
print(args)
return true
end
-- Construct and Return the command
return c.New("test", false, Execute, {})
Third Script to create and execute the command:
local c = require(script.Parent.TestCommand)
c.Exec(nil, {"does", "this", "work", "yet???"}) -- will print the table.
Something else to note which I found really cool is that type checking skills also transfer to the Swift Programming Language that was developed by Apple (doing a uni module with it included). This tutorial has been an invaluable tool that has taken me between several programming languages and helped me throughout my time at university so far.
--!strict
local Value : any = 5
print(Value + 1) -- This will shout at us because we have Value set to any, this means its not sure if this should be possible or not, this is where assertion comes in:
print((Value::number) + 1) -- This will work because we asserted that this would be possible, via setting its type to number.
-- Remember! assertion only applys for that operation if I were to now do
print(Value + 1) -- It would still shout at us