Luau Type Checking Beta!

I think I’ll need Rojo and syntax highlighting, and linting, to adapt typed Lua too. Typing is good, but my love of git as source control, as well as local files, as well as luacheck is just too good.

Although it wouldn’t take much to replace luacheck, compared to TypeScript’s validators, luacheck is quite disappointing. Hoping that this syntax parsing that Roblox is doing can be used for this sort of thing too–that would be super neat!

11 Likes

Will this allow us to create overloaded functions?

ex:

function test(x: number) => number
return x
end

function test(x: string) => string
return x
end

print(test(5))
print(test(“example”)

11 Likes

Honestly Luacheck’s already been replaced (in my eyes) by @kampfkarren’s Selene. I would recommend checking it out.

Also means he could add type (syntax*) support too.

It’s so much better.

5 Likes

This is awesome! My C# appreciations can finally become true within Roblox Lua coding.

Jokes aside, could we please shorten boolean to bool? It’s kind of a standard on many object based languages since it is slightly shorter and faster to write. We’re still in time to fix that up… right?

Regardless, love this. Thank you for this.

9 Likes

My game’s compiler minifies variable names, and using as for variables can cause compatibility problems.

local as = function()
	
end
as()

:4: Expected '=>' when parsing function type, got <eof>

I fixed it by simply adding "as" to my compiler’s list of off-limit variable names, but my game’s live build started getting server errors when requiring that module yesterday out of the blue which is pretty serious. Lots of reports of players stuck at the loading screen.

13 Likes

I am experiencing crashes while using this beta feature.

8 Likes

It appears as though method style declarations for tables aren’t supported. Unless I’m doing something wrong?

image

5 Likes

Don’t think there would be an easy way to do that with the syntax Lua has. I would recommend a union and just type guarding the result with something like t instead of relying on overloading anyway.

1 Like

For reference, I plan on preventing Selene from getting syntax errors with types ASAP. However, there are no plans to create a type checker within Selene. I’m trying to figure out how to extract information from the script analysis with a plugin until editor integration is a thing so we can use this in VSC easily.

5 Likes

Tables appear to work with recursion

type t = {[t]:t} -- perfectly fine!

But not functions

type t = (t) => t -- internal failure???
3 Likes

It appears to be related to the method syntax.

I get a warning on function myCheeseBurger:eat() but not function myCheeseBurger.eat(...) or myCheeseBurger.eat = function(...)

Not sure what that is about though and why it only happens in the case of methods.

image

Perhaps methods some how modify the table in a way that is not permitted by the “sealed table” functionality.

4 Likes

Note that we plan to ship a fully functional replacement for luacheck that uses the exact same linting engine as Studio does, and the same type checker, and a ton more things as a standalone command line tool that is kept in sync with client/studio releases. Stay tuned.

49 Likes

If I have a Script:

local Module = require(script.Module)
Module.Test(1)

And the Module:

local Module = {}

function Module.Test(Value: string)

end

return Module

II don’t suppose there’s any way to typecheck this currently. If not, will there be any future integration with modules to the type system?

1 Like

I believe as you do this you are stating there should only be one item in foo and the type of that should be a string. So you would be unable to insert a function into the table.

I don’t think that is the problem. He set the key parameter to be for strings, and the value of that key to be the any datatype.

Here is an example of some example code to illustrate what im saying.

image

2 Likes

Globals seem to always produce an issue?

what = 1

image

5 Likes

This was the most exciting feature for me when I first saw the Roblox roadmap! I can’t wait to check it out.

I do have a concern with the syntax though. There seems to be 3 different ways to annotate a type based on the context. I feel I get the reason for this, a colon is already used for denoting a method call. Whoever, having multiple ways to do the same thing can get fairly confusing, especially for new users (see C++). It is not a big deal, but considering the syntax is still volatile, I feel it is important to consider. For example, having the type before the name, separated by a space.

2 Likes

The type information for string.byte incorrectly says that it returns a string when it actually returns a number.
image

That complicates parsing dramatically because then it isn’t trivial to know whether something is a type or a variable name. Most modern languages use [name]: [type] as a result.

5 Likes

This looks like it will be very helpful! I’m glad to see so many updates that are good for developers this year!

1 Like

How do types interact between modules?

If there’s ever a “right” way to require other modules for inter-module-development, it needs to be absolutely perfect. I’ve designed dozens of module loaders, and the goal is always to design a system that’s intuitive, keeps track of dependencies, strips unused modules/code, and enable inter-module optimizations.

My game uses a system where modules reference eachother explicitly via their name and id (similar to an assetId). This means that modules are replicated as needed which provides absolutely massive load time improvements for huge games. I also completely avoid DataModel-traversal boilerplate this way.

Perhaps when you load a function from another module you can just assert its function type, so that type checks don’t need to be done upon every function call (just wherever the function is loaded in.) This would be the most flexible and can be applied to established codebases easily.

Also, this doesn’t happen often, but how will we define functions that have a circular dependency? One of them will need to be defined first before it can reference the another.

local foo;
local bar = function()
    foo()
end
foo = function()
    bar() -- not the best example
end

In some other languages they can simply reference the other when they’re in the same class, but this isn’t the case with Lua.

3 Likes