mirror of
https://github.com/luau-lang/rfcs.git
synced 2025-04-19 11:23:55 +01:00
Create metatable type functions RFC
This commit is contained in:
parent
03608c7519
commit
150014d99a
1 changed files with 77 additions and 0 deletions
77
docs/metatable-type-functions.md
Normal file
77
docs/metatable-type-functions.md
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
# 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:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local clock = {}
|
||||||
|
type Identity = typeof(setmetatable({} :: { time: number }, { __index = clock }))
|
||||||
|
```
|
||||||
|
|
||||||
|
could be reduced to:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local clock = {}
|
||||||
|
type Identity = setmetatable<{ time: number }, { __index: clock }>
|
||||||
|
```
|
||||||
|
|
||||||
|
### `getmetatable` Type Function
|
||||||
|
|
||||||
|
[Issue #1435](https://github.com/luau-lang/luau/issues/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 } }`:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local animal = {}
|
||||||
|
type Identity = setmetatable<{
|
||||||
|
sound: string
|
||||||
|
}, {
|
||||||
|
__index: animal
|
||||||
|
}>
|
||||||
|
```
|
||||||
|
|
||||||
|
### `getmetatable` Type Function
|
||||||
|
|
||||||
|
In the following code example, `ReversedIdentity` should evaluate to `{ __index: animal }`:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
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!"`:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
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.
|
Loading…
Add table
Reference in a new issue