# 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.