luau/rfcs/syntax-type-ascription.md

69 lines
2.2 KiB
Markdown

# Type ascriptions
> Note: this RFC was adapted from an internal proposal that predates RFC process
**Status**: Implemented
## Summary
Implement syntax for type ascriptions using `::`
## Motivation
Luau would like to provide a mechanism for requiring a value to be of a specific type:
```
-- Asserts that the result of a + b is a number.
-- Emits a type error if it isn't.
local foo = (a + b) as number
```
This syntax was proposed in the original Luau syntax proposal. Unfortunately, we discovered that there is a syntactical ambiguity with `as`:
```
-- Two function calls or a type assertion?
foo() as (bar)
```
## Design
To provide this functionality without introducing syntactical confusion, we want to change this syntax to use the `::` symbol instead of `as`:
```
local foo = (a + b) :: number
```
This syntax is borrowed from Haskell, where it performs the same function.
The `::` operator will bind very tightly, like `as`:
```
-- type assertion applies to c, not (b + c).
local a = b + c :: number
```
Note that `::` can only cast a *single* value to a type - not a type pack (multiple values). This means that in the following context, `::` changes runtime behavior:
```
foo(1, bar()) -- passes all values returned by bar() to foo()
foo(1, bar() :: any) -- passes just the first value returned by bar() to foo()
```
## Drawbacks
It's somewhat unusual for Lua to use symbols as operators, with the exception of arithmetics (and `..`). Also a lot of Luau users may be familiar with TypeScript, where the equivalent concept uses `as`.
`::` may make it more difficult for us to use Turbofish (`::<>`) in the future.
## Alternatives
We considered requiring `as` to be wrapped in parentheses, and then relaxing this restriction where there's no chance of syntactical ambiguity:
```
local foo: SomeType = (fn() as SomeType)
-- Parentheses not needed: unambiguous!
bar(foo as number)
```
We decided to not go with this due to concerns about the complexity of the grammar - it requires users to internalize knowledge of our parser to know when they need to surround an `as` expression with parentheses. The rules for when you can leave the parentheses out are somewhat nonintuitive.