rfcs/docs/type-metamethod-support.md
2024-10-04 09:59:01 +01:00

2 KiB

Type Metamethod Support

Summary

Add support for the __type metamethod on Luau defined tables.

Motivation

The motivation of allowing developers to use the __type metamethod is to provide a better runtime mechanism for comparing between table types.

Right now, the type checker can compare table types, however, using typeof on these tables will still return table, as to the runtime, these are the same type. Support for the __type metamethod is already supported for host-defined userdatas, so it would be trivial to extend this to tables.

Design

The design would simply involve adding a new metamethod __type, that can be set in the metatable of another table:

local Cat_MT = {
  __index = Cat,
  __type = "Cat"
}

When calling the Cat object with typeof, it should return the value of the defined __type metamethod if it exists:

local cat = Cat.new()
print(typeof(cat)) --> "Cat"

Drawbacks

The main drawback is that this allows spoofing of host-defined userdatas, lets take the Roblox datum Color3. This object contains a __type flag of Color3. If we allow __type on userdatas, there's no easy way to check between a host-defined userdata, and a spoofed Color3 Luau userdata/table at the Luau level.

The easiest fix is to include a hardcoded prefix on the __type field to indicate its a Lua-defined table.

Alternatives

This can already be implemented using a field exposed on the table:

local t1 = {__type = "Table1"}
local t2 = {__type = "Table2"}

local function useTable(t)
  if t.__type == "Table1" then
    print("table is of type 1")
  elseif t.__type = "Table2" then
    print("table is of type 2")
  end
end

The issue here is that it requires each table passed to the function to implement a __type field, which has its own problems

  • If the table is not frozen (or cant be frozen), someone can easily change the __type field and make the code take a path other than expected.
  • It creates a contract that every object table has a key of the same name to check types.