Luau Recap: July 2021

Yeah I really loved the condition already being checked update. This is helpful in reducing lag as well as unnecessary code.

The table operations update confused me a little bit at first but adding parenthesis did indeed remove the annoying little tick under the table addition.


I reported a bug in February in the Luau linter, where if you index script.NameGoesHere, it will show that “Key ‘NameGoesHere’ not found in class ‘Script’” if there is no such Instance when the line of code is written, but even after inserting something named “NameGoesHere” it just won’t go away until restarting Studio.

The new linter improvements are great, but please fix this or tell us that there’s something that prevents an easy fix. It’s very distracting, and the only reason I don’t have the “Scripts Are Non-Strict by Default” beta on.


Little tip—you can actually drag the script up in the explorer (reparenting it to something else), and then drag it back to where it was to refresh the linter and get rid of these warnings. I usually do this whenever I’m referencing children of scripts which I add as I write the code, and I have strict mode on all of my code right now.

It is annoying how some warnings can cache like this though.


what is confusing about people saying luau?

1 Like

It was because I thought the Roblox language was Lua.


task.wait seems to be implemented for testing, wondering if there’s any plans to make it better for mass use, even though polling is bad of course, I guess there’s people that need heavy usage, and even task.wait from my understanding shouldn’t be fixing the entire wait lagging with multiple threads being resumed and yielded at once,

which this library helps with:

1 Like

Can someone show me a code example of task.wait?

1 Like

This looks great! I’ll keep waiting for luau to have destructuring dictionaries syntax like that of Javascript :joy:

Something like:

local names = {
   ["harry"] = {
      location = "usa",
      age = 17
   ["bob"] = {
      location = "canada",
      age = 14
local { harry, { age } } = names -- data of harry and age of bob destructured.   
1 Like

had parallel Lua been released? I realized that the task library is implemented, and I haven’t had the beta enabled for weeks


It’s basically a more accurate version of wait() .

See reply below.

The biggest difference isn’t so much the precision, it’s the fact that it doesn’t throttle: task.wait(delay) will unsuspend after the delay regardless of what the consequences may be, compared to wait(delay) which “helpfully” throttled execution for you, sometimes delaying resumption by extra frames to keep the frame rate smooth (something which frequently frustrated devs because they didn’t have much control over the throttling).


Found another issue with the type checker! Is this the right place?!?

Seems like your type constraint resolver doesn’t properly handle table (or Instance) properties when inferring types. They do not respect conditional logic whatsoever, which is annoying since I don’t want to create a variable just to reference a property I hardly ever use.

local basepart: BasePart
local model: Model ="Model")

assert(model.PrimaryPart, "Model must have a PrimaryPart!")

basepart = model.PrimaryPart


In this case, model.PrimaryPart is inferred as BasePart? when it should be BasePart since it passes the assert call earlier on.

This applies to tables as well:

local t: { foo: string? } = { foo = nil }
local str: string

if then
	str =


As said before, an easy way to solve this is by using a variable. However, this is a minor inconvenience with rarely-used properties that often don’t require caching.


I believe a “sweeter” way of getting around this is with the type casting operator (str = :: string)

This should definitely be fixed but that might be a cleaner way of getting around it.


This is known and is on the shortlist of planned improvements.


Found a minor bug with the way types are displayed.

This code should be perfectly sound, and indeed emits no warnings:

local alwaysReturnsANumber = function() return 2 end
local sometimesReturnsACallback = function(): typeof(alwaysReturnsANumber)?
	if math.random() > 0.5 then
		return alwaysReturnsANumber :: any
		return nil
local callback = sometimesReturnsACallback()
if callback then
	local number = callback()
	print(number + 3)

However, whenever I hover over the type of the variable callback (via the “Luau-Powered Type Hover” beta feature), it tells me that callback is of type () -> number?

This means that the callback definitely exists and will optionally return a number. It should really be displayed as (() -> number)? since it is optionally a callback that always returns a number.

This has confused me on multiple occasions. Adding the following line to the end of that code will lead to a funky looking warning:

local x: () -> number? = callback

Type '() -> number?' could not be converted into '() -> number?'

Obviously, this is just a display issue, and it really should be saying Type '(() -> number)?' could not be converted into '() -> number?' or vice-versa

1 Like

Will we still be able to script in Lua?

1 Like

Luau is syntactically backwards compatible with Lua 5.1. So yes, all Lua 5.1 code you wrote is still valid Luau code.

1 Like

Thank you for the report, a fix for this will be included in the next update.


Equality comparison between nullable and non-nullable type should probably be allowed?


This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.