Typechecking bug or misunderstanding: Expected type table, got nil instead

I’m using strict mode (--!strict) and I’m having a problem where I get an “Expected type table, got nil instead” warning after using Instance:Clone().

I can dismiss the warning by adding another if-then block to confirm the Instance exists.

However, I feel like that’s unnecessary because Instance:Clone() returns Instance , not Instance?.

Is this a bug with the type-checker or am I doing something wrong?

Strange, looks like :Clone() returns nil if the instance is not Archivable.

2 Likes

That’s a good observation because Instance:Clone() actually does return nil if Instance.Archivable is false. Despite this, the same warning occurs even if Instance.Archivable is certain to be true.

image

2 Likes

Now that I’ve written down your example, I realized the warning has nothing to do with what :Clone() returns.

SpecialScript = Instance.new("ModuleScript")
SpecialScript.Name = "..." -- warning appears

SpecialScript is declared without type notation, so it doesn’t have any “locked” assigned type (although it’s nil) until something is assigned. I assume what bothers the type inference system is that SpecialScript may either be nil or ModuleScript after the loop.

Considering this example:

--!strict

local function TakeAChance(): string
	local outcome --: string?
	
	if 1 == 2 then
		outcome = nil -- whichever type
	end
	if not outcome then
		outcome = math.random(0,1) == 0 and "heads" or "tails"
	end
	return outcome
end

Try defining SpecialScript as ModuleScript?.

1 Like

Clone doesn’t return Instance, it returns the same type that it’s called with.
The type checker is far from perfect but check the types you have on your SpecialScript and Template.

Screenshot 2023-07-18 at 3.55.16 PM

2 Likes

everything points to a bug in the type checker, probably because it is not sophisticated enough yet.

The problem has to do with type refinement
image

when a refined variable is used, its type is the one that was inferred by the refinement, while in the assignment its type remains unrefined.

I have come to this conclusion from experimentation. Although the luau code is available, I am still not able to understand it.

if you want to get around this bug you can do so by creating a temporary variable.

2 Likes

Yeah, this issue is very similar to this simplified example:

--!strict
local function GiveMeAName(part: Part, name: string?): string
	name = name or "Jeff"
	part.Name = name --> name underlined, type is clearly a string
end

Because there’s a possibility there may be no name argument, type checker doesn’t (yet) see that name cannot be anything but a string when assigned.

After the temporary variable is created, it’s type is assigned once it starts pointing to the cloned module. SpecialScript is still subject to warnings because the type system deems it possibly nil.

image

Another solution is to reasure the type checker that SpecialScript will definitely exist.

image

I tried but the warning does not go away.
Even if i put Configuration? and Folder? and then check if the clone exists before setting the parent.

image

The following passes without problems when I create one variable for each acceptable type:

image

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