Luau Recap: March 2020

I can’t tell if this is a bug or not.

If you input this in the command bar, it shows userdata. In the old VM, it would show Color3

-- Output: userdata

Are you sure you’re not thinking of typeof?

type( -> userdata
typeof( -> Color3

Could we get a notification for the change for the new Luau type checking syntax is out? (In script analysis saying the syntax changed.) I’m already using it in a game and it’d be helpful to know when the function syntax for returns is changed so I can update my code.

Also I’m currently having an issue with Luau type checking in the same game where I get these from script analysis today: (Wasn’t happening before today.) (Isn’t happening with just chat scripts, doesn’t show any syntax issues on my actual scripts either.)

I’ve restarted studio twice and these are still here, I’m guessing there’s an issue with a recent change.

I don’t know if the new type annotation syntax change have been rolled out, but the function type declaration seems to produce error while function definition does not.


It will be fully enabled later today.


I have a basic function:


function test(foo: string): number
	return #foo


This is the output for the above code:

I’m assuming this is some sort of bug? What’s going on here?

Edit: Some bonus snippets as well, clarification here would be great, I’m at a loss:


local test: NotAType = 1
print(test) --> 1

type foo = {bar: string}
local test: foo = {foo = "Hello World", bar = 10}
print( --> Hello World
print( --> 10

Shouldn’t all of these scenarios not work in strict mode? I can’t find anything about the syntax for enabling strict mode changed, am I missing something here?

1 Like

Do you have the Beta feature enabled?


If you do, you should have both of these display issues in Script Analysis widget. Note that type errors don’t block your ability to run the code right now.


Studio disabled all of my beta options in the recent studio build and I was not aware of this until now. I had them all enabled. I didn’t think to check for that reason. I have no clue why, but that’s a separate issue.
edit: Studio did crash mid-session when trying to update, I can provide a crash report if you’d like, it could be related to the issue.

I’ve been rewriting my framework with type checking, and it’s been pretty smooth other than two major issues I’ve faced:

  1. Requiring third party modules without type checking implemented, in non-strict mode, such as eryn’s “Promise” and Quenty’s “Maid” take exactly one second to require for the first time, every time. This means that it can take up to 10 seconds for any code to run, as the script is stuck requiring these modules for a long time. This is not the case with my custom libraries which are scripted with type checking. No code in the project is currently using strict mode, however all the first party code that I am writing is designed to be strict mode ready later.
  2. I forgot I didn’t have studio API access enabled in my test place, and trying to use DataStoreService:GetGlobalDataStore() did not error, but rather the script requiring the module threw a “Requested module experienced an error while loading” error which would always throw approximately 2 seconds after initially requiring the module.
    After further investigation, I’ve found niche cases where my own functions can have this behavior, too, making debugging with modules no easy task.

These two issues have made my experience really daunting, but other than that it’s been smooth sailing. Could you advise on why I’m getting such behaviors? This did not occur when all the scripts were written without heavy type checking support.


I don’t really like this update, broke some of my code:

local function noyield(f,...)
	return select(2,assert(xpcall(f,debug.traceback,...)))

It was imo a clean wrapper to call functions and error if the function yields (very useful for non-production code). Now I have to switch to __index or a for loop iterator call (or is there a cleaner way?) to get this same behavior.

I think we can always make a yielding xpcall ourselves (is this wrong?):

But ideally the above noyield is Roblox provided and imo xpcall shouldn’t exist (if the above is just as powerful).

For loop iterator call is probably the fastest alternative. A cleaner alternative is to use coroutine.create/resume (and check status) but that can be expensive.

You could not make a yielding xpcall yourself, as the callback in xpcall executes in context of the error, making debug.traceback work.

Sorry this affected you, these things happen - it’s much better for us long term to have uniform expectations about pcall and xpcall though, and for every use case when xpcall was used to block yields there’s several opposite use cases where xpcall is desireable but didn’t work and had to be emulated.

1 Like

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