"Value could be nil" Type Error When It Cannot Be Nil

Ran into this error today warning that the UISizeConstraint might not exist even though the if statement guarantees it.

Edit: upon further examination, it appears this only happens when the object being searched inside of is explicitly typed and not just inferred.

1 Like

Correct me if I’m wrong, but I think that from the type-system’s point of view, nothing is known about the specifics of the behavior of a function like FindFirstChildWhichIsA. It just knows that it is a function that takes in a string, and in the case that the provided string is of the singleton string type "UISiceConstraint", the function returns UISiceConstraint?. The way to work with this would be to make the result of the function call a variable and then type-narrow that with if statements like you do with the function call.

1 Like

As @OptimisticSide said:

image

It doesn’t look like the Type System is intelligent enough or has enough information to understand that there are no possible side-effects between those two lines. It doesn’t know whether or not :FindFirstChild depends on something other than script, it doesn’t know if script itself changes, all it knows is that the return type is optional and could be nil.

The type system is correct; narrowing the return of one function call does not mean that it narrows the next. Two calls to FindFirstChild with the same argument can return different results. It would be an error if the type system suggested otherwise.

In this case it is incorrect as :FindFirstChild does not “yield” (i.e. allow the Engine to interrupt the Script and work on other tasks), and because :FindFirstChild itself does not modify any Instances, there’s never any opportunity for the state of the game to change in-between those two calls, whether through the Engine or through another Script.

What you have described is not the responsibility of the type system to determine. It checks types, not if your code can affect world state or if it yields. It’s not aware of runtime-specific features. You can perform a similar replication in TypeScript or C# (albeit C# being more forgiving and just giving a warning, rather than a compiler error). Besides other languages, what is the type system meant to do in the following example?:

if script:FindFirstChild("A") then
    -- playing devil's advocate, let's say this line gives no type error
    script:FindFirstChild("A").Name = "abc"
    script:FindFirstChild("A").Parent = workspace

    -- what do we do here? the type checker has no knowledge of the world; 
    -- this could be nil or it could refer to another `A`
    script:FindFirstChild("A").Name = "abc"
end

As it stands, the type system is correct, and code should make use of the result and its narrowed type rather than throwing it away for a second function invocation.

1 Like

:slight_smile: I am saying that in this specific situation it is incorrect as there is no space for any of this to happen. Your original reply felt a little dismissive to the original context, not a hypothetical wherein this warning would be valid.

1 Like