Warning when using types with short-circuit evaluation

I am using types where the first variable can either be of type Vector3 or nil. However when I create a new variable with type Vector3 and set it to the first variable using short-circuit evaluation, it gives me a warning. As you can see I do a check to see that v is a Vector3, but that still causes a warning with the message: “Type mismatch Vector3 and Vector3 | boolean | nil”.

local v: Vector3? = Vector3.new(1, 1, 1)
local u: Vector3 = typeof(v) == 'Vector3' and v -- Here I get: Type mismatch Vector3 and Vector3 | boolean | nil

-- Alternative way below with a different warning: Type mismatch Vector3 and Vector3 | boolean
-- local u: Vector3 = typeof(v) == 'Vector3' and Vector3.new(v.X, v.Y, v.Z) 

It seems like it is complaining about that variable u can get the type of a boolean. I know that a different way of doing the same thing is to just use an if statement, where I don’t get any warnings, like this:

local v: Vector3? = Vector3.new(1, 1, 1)
if typeof(v) == 'Vector3' then
	local u: Vector3 = v
end

However I would like to hear from you what causes the warning when doing it the first way and if it is possible to fix it.

You get it here because there is a chance typeof(v) == 'Vector3' can result in false therefore v won’t be evaluated.

You could do what you want conditionally:

local u: Vector3 = typeof(v) == 'Vector3' and v or some_other_vector

so that it always evaluates to a Vector3.

Alright, I see what is happening.

When attempting doing the way you suggested it still didn’t work, since now i get a type mismatch between Vector3 and Vector3 | nil.

local v: Vector3? = Vector3.new(1, 1, 1)
local w: Vector3 = Vector3.new(1, 2, 3)
local u: Vector3 = typeof(v) == 'Vector3' and v or w

Looks like it may be a bug? I dont have any issues with the linter when transposing the statement as a function

local v: Vector3? = Vector3.new(1, 1, 1)
local w: Vector3 = Vector3.new(1, 2, 3)

local function foo(givenVector: Vector3?): Vector3
	return v or w
end

local result: Vector3 = foo(v)

That said, I DONT get a lint when I would expect one when giving the result value Vector2? Anything else seems to give me the expected lint though.

local v: Vector3? = Vector3.new(1, 1, 1)
local w: Vector3 = Vector3.new(1, 2, 3)

local function foo(givenVector: Vector3?): Vector3
	return v or w
end

local result: Vector2 = foo(v)
2 Likes

Are you sure that you are using the --!strict flag? I get a warning around the return in the function with the flag, and no warnings without it.

Ah no, I was not. Strangely your previous example was occurring even without the strict flag. I’m having a hard time finding any documentation on the type system so I’m not sure if this is expected behavior. Sorry I’m not much help.

1 Like