Skip to content

Propose: Syntax-types-number-literals.md #112

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

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
Development

Successfully merging this pull request may close these issues.

4 participants