2.7 KiB
Metatable Type Functions
Summary
Implement type functions for getmetatable
and setmetatable
.
Motivation
setmetatable
Type Function
There is currently no way for users to apply metatable type information to a type without the usage of typeof()
. This isn't ideal, as it adds verbosity and boilerplate to common patterns such as object-oriented programming. For example, the following:
local clock = {}
type Identity = typeof(setmetatable({} :: { time: number }, { __index = clock }))
could be reduced to:
local clock = {}
type Identity = setmetatable<{ time: number }, { __index: clock }>
getmetatable
Type Function
Issue #1435 is caused by a lack of special behavior for getmetatable
when the type's metatable has a __metatable
field. This is fixable in a variety of ways, however a type function has multiple benefits and exposes more type-level expression for users. It fits in nicely with the new solver, as type functions are a cleaner alternative to magic functions.
Design
setmetatable
Type Function
In the following code example, Identity
should evaluate to { sound: string, @metatable: { __index: animal } }
:
local animal = {}
type Identity = setmetatable<{
sound: string
}, {
__index: animal
}>
getmetatable
Type Function
In the following code example, ReversedIdentity
should evaluate to { __index: animal }
:
local animal = {}
type Identity = setmetatable<{
sound: string
}, {
__index: animal
}>
type ReversedIdentity = getmetatable<Identity>
Due to __metamethod
, additional behavior needs to be met. In the following code example, MetatableType
should evaluate to "No metatable here!"
:
type metatable = {
__metatable: "No metatable here!"
}
type MetatableType = getmetatable<setmetatable<{}, metatable>>
Drawbacks
Introducing a large library of "global" type functions can clutter naming space for users.
The name of setmetatable
has an interpretation of implying a side effect; tables are references, and setmetatable
is a side-effecting function. It could be argued that setmetatable
is not a good name for a type function which has no side effects. However, consistency is desirable. A slight rename of a global function could cause confusion, and likely cause mistakes to be made. Type functions also have a precedent of not allowing side effects, so therefore a setmetatable
type function would not have ambiguity when it comes to side effects.
Alternatives
Do nothing. typeof
solves the current issues with accessibility to the current object-oriented programming patterns, and the issue relating to getmetatable can be solved by overloads.