Skip to content

Conversation

@ssynical
Copy link

@ssynical ssynical commented Apr 4, 2025

Comment on lines +94 to +109
### Generic Constraints

Number literal types can be used as generic constraints:

```lua
local function createArray<T, N: number>(value: T, length: N): {T}
local arr = {}
for i = 1, length do
arr[i] = value
end
return arr
end

local arr1 = createArray("hello", 3) -- OK: Creates array of length 3
local arr2 = createArray("world", -1) -- Type error: Negative length
```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section describes features which do not exist in Luau.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So sorry about that, I meant something like this:

local function createArray<T, N: 1 | 2 | 3>(value: T, length: N): {T}
    local arr = {}
    for i = 1, length do
        arr[i] = value
    end
    return arr
end

local arr1 = createArray("hello", 3)  -- OK: Creates array of length 3
local arr2 = createArray("world", 4)  -- Type error: 4 is not compatible with '1 | 2 | 3'

Again, I apologise for that. No idea where my head was at.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generic constraints do not exist in Luau at all. <N: 1 | 2 | 3> is not legal syntax right now.

4. ***Type Explosion!*** Developers might create excessive unions of number literal types, leading to verbose type annotations.
5. ***Limited Usefulness***: In many cases, using enums or string literal types might be more appropriate and readable than number literal types.

## Alternatives
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add "implement this only for integers" as an option. Decimals could get pretty scary.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Integer literals is a viable alternative, yeah.

end

local function isEven(n: number): 0 | 1
return n % 2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Woah, do we expect this will just work without more explicit casts? Your later writing suggests mathematical cases like this are NOT inferred. If that's not the case then you'll need to be more explicit that % does work like this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this type isn't even correct. 0.5 % 2 == 0.5.

Comment on lines +40 to +41
local function setVolume(level: 0 | 1 | 2 | 3 | 4 | 5): boolean
-- Only accepts volume levels 0-5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As written, this would accept the literal integers, 0, 1, 2, 3, 4, and 5, not all numbers on the range [0, 5]

Comment on lines +74 to +84
The type checker will infer the most specific type when dealing with number literals:

```lua
local x = 42 -- Inferred as '42', not 'number'

local function double(n)
return n * 2
end

local y = double(5) -- Inferred as 'number', not '10'
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a huge departure from how type inference works today for every singleton type. We default to inferring string and boolean, unless the context requires that the singleton type be inferred.

Comment on lines +94 to +109
### Generic Constraints

Number literal types can be used as generic constraints:

```lua
local function createArray<T, N: number>(value: T, length: N): {T}
local arr = {}
for i = 1, length do
arr[i] = value
end
return arr
end

local arr1 = createArray("hello", 3) -- OK: Creates array of length 3
local arr2 = createArray("world", -1) -- Type error: Negative length
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generic constraints do not exist in Luau at all. <N: 1 | 2 | 3> is not legal syntax right now.

4. ***Type Explosion!*** Developers might create excessive unions of number literal types, leading to verbose type annotations.
5. ***Limited Usefulness***: In many cases, using enums or string literal types might be more appropriate and readable than number literal types.

## Alternatives
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Integer literals is a viable alternative, yeah.

These can be combined with union types to represent a set of allowed values:

```lua
type HttpSuccessCode = 200 | 201 | 202 | 204
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a bad motivating example.
HTTP defines all 2xx codes to be in the successful category.
Will this RFC make people write more error-prone code like this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants