Luau Type Checking Beta!

In “curly bracket languages”/C-derived languages, assignments like that can be expressions.

JavaScript example

let i = 0;
let j = i += 3;

j is assigned to i + 3, and i is actually incremented by 3.

// Don't believe me?
console.log(`i is ${i} and j is ${j}`);
3 Likes

With strict mode enabled I get an error with pcall.

image

Error: Arugument count mismatch. Function takes 2 arguments but you passed 1

This only seems to happen if I don’t return anything inside the function.

1 Like

We intentionally chose boolean to be consistent with print(type(true))

7 Likes

I’m getting a warning that I shouldn’t be getting:

local t = {}
do
	local y = t
	y.f = function(x)
		return x + 1
	end
end
local n = t.f(5)

It says: W000: (8,11) Key 'f' not found in table t
Of course this is a simplified example, but its giving me warnings over a large piece of code due to how I wrote it.

5 Likes

simple just let us program stuff in C++ or C# then ( ͡° ͜ʖ ͡°)

6 Likes

Is there any way that a type can be used across scripts? For example, I have one module that defines a type “Options”:

type Options = {
    Delay: number
}

And then in another script I’m using this module and want to create a table specifying the options:

local options : Options = {
  Delay = 5
}

But this causes an error because it doesn’t recognize the type “Options”. Other than having the type redefined, is there any other way to reuse the same type across different scripts?

2 Likes

Except you can’t effectively sandbox that stuff. The whole reason roblox uses lua cause it’s a sandbox language. They probably don’t want a snoopy developer poking about somebodies PC on their platform. That just screams legal issues.

1 Like

Found this mistake
image

3 Likes

I also have this with os methods.

1 Like

With these changes coming, will existing Lua-written code in my games be “deprecated,” in terms of like having to go back and make countless syntax changes so my whole game doesn’t break?

2 Likes

No, your code is safe.

We are committed to supporting all existing Lua code with no changes. Every last line of it. This is why we had to disable some parts of this update that inadvertently changed the meaning of some existing syntax. If your code parses and runs today, it will continue doing so tomorrow.

We intend to enable non-strict mode by default in the future. What it would mean is that your existing code might get type warnings in Studio - think of it as more script analysis warnings. You can act on them or you can choose to keep your code as is - it will work regardless. Our intention for non-strict mode is to produce the minimum amount of false positives while still being useful.

If you want to, at some point, go back to your old code and add type annotations / enable strict mode to get some guarantees about type safety - it’s your call. The code will continue to work regardless.

10 Likes

That’s awesome.

Thanks for the breakdown :slight_smile:

1 Like

This bug just bit me hard and it took me a while to figure it out.

1 Like

This is fine:

local part = workspace:FindPartOnRay(ray, nil, true, true)

This is not:

local part, hitPos = workspace:FindPartOnRay(ray, nil, true, true)


This is fine:

ghost.CFrame = hitPart.CFrame * CFrame.new(hitNormal)

This is not:

ghost.CFrame = CFrame.new(hitNormal) * hitPart.CFrame

W000: Key 'GetComponents' not found in table Vector3


I won’t be able to use strict mode for my scripts until I can write warning-free (OCD). I think the first case is due to the analyzer (or whatever) not recognizing that FindPartOnRay returns multiple values. The second case… I don’t even know.

4 Likes

I just started playing with this. Even in nonstrict it caught a real bug in some of my test code!

I think I’d like a pragma or something that would let us go back to the old behavior on certain lines or files - code I took from somewhere else for example.

Not being able to use the new types in publish makes me reluctant to try them out, it’s work that I’d have to back out of.

Is this post the only documentation of it so far?

2 Likes

I’d like to bump the circular function call question - what’s a good practice there? This is a contrived example:

function combined( n )
    return fib(n-1) + fib(n-2)
end

function fib( n )
    if n == 1 then
        return 1
    end
    if n == 2 then
        return 3
    end
    return combined(n)
end

Warns that fib() hasn’t been declared.

I’ve got a less contrived example in my codebase right now.In C I’d forward declare but that seems risky here (though no less risky than what the code’s currently doing.) Not to mention a forward declaration like this:

function fib(n)
      error( "fib used before defined" )
end

gets duplicate definition when fib really does get defined.

2 Likes

Here’s an odd one

local Namespace = {}

function Namespace.SelflessTwoParams(a,b)
  return a+b
end

function SelflessEllipsis(...)
  return Namespace.SelflessTwoParams(...)
end

SelflessEllipsis(1,2)

gets me “This function must be called with self. Did you mean to use a colon instead of a dot?” on line 9

3 Likes

This only happens with New Lua Script Analysis.

Code:

(CFrame.new(0, 0, 0) * CFrame.Angles(0, 0, 0)):ToWorldSpace(CFrame.new(0, 0, 0))

Linter: “Cannot have methods on non-table type CFrame | Vector3”. But I can!

Windows 10.

4 Likes

I know I am asking it a second time, but please it is important: do we have to write like this? I just find this new writing style too difficult and find no advantage in it.

1 Like

You won’t have to write it that way, but you will lose a lot of potential performance gains. It was pointed out that existing games will continue running normally.

4 Likes