Update support-for-type-packs-in-user-defined-type-functions.md

Major change: 
Separated packs from the type userdata since packs are not types.
This commit is contained in:
Tenebris Noctua 2025-04-13 18:33:09 +03:00 committed by GitHub
parent e56c2b4213
commit 94304b2e57
Signed by: DevComp
GPG key ID: B5690EEEBB952194

View file

@ -13,16 +13,16 @@ This limits the usage for packs as they are used often in the language, and thei
## Design ## Design
We introduce a new runtime type called `pack` to extend the support of type packs within the type runtime. We introduce a new userdata called `pack` alongside `type` to extend the support of type packs within the type runtime.
Packs will have a `kind` property that specifies the kind of the pack. A pack can either be a `list` kind or a `variadic` kind. `pack` instances will have a `kind` property that specifies the kind of the pack. A `pack` can either be of a `literal` kind or of a `variadic` kind.
For example, consider a variadic type pack (e.g `...number`), in the new pack type, it will be represented as a `pack` with a `variadic` kind. For example, consider a variadic type pack (e.g `...number`), in the new pack type, it will be represented as a `pack` with a `variadic` kind.
Or for a normal type pack such as `(number, string)`, it will be represented as a `pack` with a `list` kind. Or for a normal type pack such as `(number, string)`, it will be represented as a `pack` with a `literal` kind.
`list` kind of packs will be able to contain other packs, or types more than one, whereas `variadic` type of packs will only contain *one* type. `literal` packs will be able to contain other packs, or types more than one, whereas `variadic` kind of packs will only contain *one* type.
The user will be able to obtain the types within `pack`s using the `:unpack()` method, this method will return a table containing all the types or type packs within the pack. The user will be able to obtain the `type`s within `pack`s using the `:unpack()` method, this method will return a table containing all the `type`s or `pack`s within the `pack`.
In `variadic` kind of `pack`s, `:unpack()` will only return a table with one element. This is because variadic packs are essentially many elements of the same type. In `variadic` kind of `pack`s, `:unpack()` will only return a table with one element. This is because variadic packs are essentially many elements of the same type.
In user-defined type functions, type packs can be created by providing types or type packs that will be included within the pack. A pack will also be able to contain other packs, even packs of different kinds. In user-defined type functions, type packs can be created by providing types or type packs that will be included within the pack. A pack will also be able to contain other packs, even packs of different kinds.
@ -32,10 +32,9 @@ In user-defined type functions, type packs can be created by providing types or
Creating a type function that accepts type packs: Creating a type function that accepts type packs:
```luau ```luau
type function f(arg: type) type function f(arg: pack)
if not arg:is("pack") then error("The given argument is not a type pack!") end if typeof(arg) ~= "pack" then error("The given argument is not a type pack!") end
local unpacked = arg:unpack() -- {string, number} local unpacked = arg:unpack() -- {string, number}
print(unpacked)
end end
type a = f<(string, number)> type a = f<(string, number)>
``` ```
@ -44,8 +43,9 @@ Creating a type function that returns a function with a type pack:
```luau ```luau
type function f() type function f()
local newListPack = types.pack({types.string, types.number}) local newPack = types.pack({types.string, types.number}) -- (string, number)
local newVariadicPack = types.pack({types.any}, true) local newVariadicPack = types.pack({types.any}, true) -- ...any
local newfunc = types.newfunction() local newfunc = types.newfunction()
newfunc:setparameters({newPack}, newVariadicPack) newfunc:setparameters({newPack}, newVariadicPack)
newfunc:setreturns({newPack}, newVariadicPack) newfunc:setreturns({newPack}, newVariadicPack)
@ -58,7 +58,7 @@ The pack type will also enable generic type packs to be provided to type functio
Generic type pack arguments will pass the given type pack to the type function. Generic type pack arguments will pass the given type pack to the type function.
```luau ```luau
type function createCallback(args: type, returns: type) -- args will be a list pack, returns will be a variadic pack. type function createCallback(args: pack, returns: pack) -- args will be a literal pack, returns will be a variadic pack.
local newTable = types.newtable() local newTable = types.newtable()
local newfunc = types.newfunction() local newfunc = types.newfunction()
newfunc:setparameters({args}) newfunc:setparameters({args})
@ -74,35 +74,40 @@ If variadic type functions were to be implemented, type packs could be retrieved
```luau ```luau
type function f(...) type function f(...)
local packed = {...} -- {type} local packed = {...} -- {pack}
local firstPack = packed[1] -- type.kind: list local firstPack = packed[1] -- pack.kind: literal
local secondPack = packed[2] -- type.kind: variadic local secondPack = packed[2] -- pack.kind: variadic
end end
type a = f<(string, number), ...number> type a = f<(string, number), ...number>
``` ```
## Updates to the types library and type userdata Evaluating `typeof(...)` on a `pack` userdata will give the string `"pack"`.
```luau
type function f(arg: pack)
print(typeof(arg)) -- "pack"
end
type a = f<(string, number)>
```
## New pack userdata
### `pack` Instance
| New/Update | Instance Properties & Methods | Type | Description |
| ------------- | ------------- | ------------- | ------------- |
| New | `kind` | `"literal" \| "variadic"` | indicates the kind of the `pack`. |
| New | `unpack()` | `{pack \| type}` | returns the `type`s contained within the `pack`, returns only one element if `kind` is `variadic`. |
## Updates to the types library and the type userdata
### `types` Library ### `types` Library
| New/Update | Library Functions | Return Type | Description | | New/Update | Library Functions | Return Type | Description |
| ------------- | ------------- | ------------- | ------------- | | ------------- | ------------- | ------------- | ------------- |
| New | `pack(types: {type} isvariadic: boolean?)` | `type` | returns an immutable instance of a type pack; when `isvariadic` is true, `types` table can only have one type. | | New | `pack(args: {pack \| type}, isvariadic: boolean?)` | `pack` | returns an immutable instance of a type pack; when `isvariadic` is true, `args` table can only have one `type`. |
| Update | `newfunction(parameters: { head: {type}?, tail: type? }, returns: { head: {type}?, tail: type? }, generics: {type}?)` | `type` | `tail` arguments can now accept variadic packs. | Update | `newfunction(parameters: { head: {type}?, tail: type? }, returns: { head: {type}?, tail: type? }, generics: {type}?)` | `type` | `tail` arguments can now accept variadic packs.
### `type` Instance
| New/Update | Instance Properties | Type | Description |
| ------------- | ------------- | ------------- | ------------- |
| Update | `tag` | `"nil" \| "unknown" \| "never" \| "any" \| "boolean" \| "number" \| "string" \| "singleton" \| "negation" \| "union" \| "intersection" \| "table" \| "function" \| "class" \| "thread" \| "buffer" \| "generic" \| "pack"` | Added `pack` as a possible tag |
#### Pack `type` instance
| New/Update | Instance Methods | Type | Description |
| ------------- | ------------- | ------------- | ------------- |
| New | `kind` | `"list" \| "variadic"` | indicates the kind of the pack. |
| New | `unpack()` | `{type}` | returns the types contained within the pack, returns only one element if `kind` is `variadic`. |
#### Function `type` instance #### Function `type` instance
| New/Update | Instance Methods | Return Type | Description | | New/Update | Instance Methods | Return Type | Description |