LuaLS / LuaLS/lua-language-server

Feature Request: Assertion Functions

Open
#2,032 5 comments 5 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
Lua
Stars
4.4k
Forks
442
PR merge metrics
No merged PRs in 30d

Description

I would like annotation and type checking that supports and implements TypeScript's "Assertion Functions":
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions

It's similar to other open feature requests for type predicates / narrowing except it avoids the need for if statements and to return a boolean from the function where `true` means a variable is of a given type and `false` if it's not that type.

I mentioned this briefly in another open issue but the original issue was for implementing narrowing/type predicates:
https://github.com/LuaLS/lua-language-server/issues/704#issuecomment-1484060572

This TypeScript code illustrates the feature:

```ts
function assertIsString(val: any): asserts val is string {
if (typeof val !== "string") {
throw new AssertionError("Not a string!");
}
}
```

This tells the linter that the argument passed to the `val` parameter is a string if no assertion raised an error.

In Lua, this might look like the following:

```lua
---@param val any
---@asserts val is string
local function assertIsString(val)
assert(type(val) == "string", "Not a string!")
end

---@param str any
local function yell(str)
assertIsString(str)
-- No error was thrown! Therefore, the next line should not be marked as a warning and `str` must be a string.
return str:upper()
end
```

The problem at the moment is that I need to add `---@cast val string` after every usage of `assertIsString`:

```lua
local function yell(str)
assertIsString(str)
---@cast str string
return str:upper() -- LuaLS complains that str might not be a string unless I cast it
end
```

There is no other way of telling LuaLS that the result has been confirmed to be a string unless the `assert` expression is directly in the same body of code.

I would suggest adding `narrowing` with type predicates first as this feature request seems like the next feature on top of that feature, but I'd like to see what people think :)

Thank you!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the TypeScript 3.7 assertion-functions reference and the linked type-predicate issue 704, then inspect how existing @cast annotations perform narrowing. Done means a Lua assertion annotation can narrow the argument after a successful assertion call, so the yell example accepts str:upper() without a separate cast.

Written by the indexing model from the issue text.

Assessment

Tech stack
lua, typescript
Domain
tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.