Difference between "any" and "any?"

I don’t really understand what’s the difference between these two types. Because we usually use “?” in order to highlight that variable can be “nil”. But “any” already can be “nil”, so why would I again say that it could be “nil”?

2 Likes

If you use any, then it can return any type of value
however…
If you use any?, then it can return any type of value or a nil

That is how I am interpreting it

But you can set variable of type “any” to nil.

1 Like

I believe that adding a question mark simply allows (for example) parameters which are empty to not error. Although your insight suggests that it isn’t needed so I’ve no idea ¯_(ツ)_/¯

Because you already know it could be empty.

If I’m not mistaken, any implies any non-nil value, while any? also accounts for nil.

But I uploaded a screenshot earlier that in fact you can set variable of type any to nil.

I guess it’s great way of thinking when you write your own code, but unfortunately solver doesn’t have same opinion.

Both (any / any?) can return nil, you are correct. But if you use any?, it kind of implies that you already know nil could be returned so your writing the code already knowing. lol it is confusing.

Fortunately or unfortunately there is no difference

Both just mean “any value at all,” but neither force nil checking. So, unknown is probably better when you want to prevent nil index errors in places where the types are unknown.

4 Likes

as the person above said, no difference at all, its just how the syntax works, it’s just a weird addition that you can do any? and it doesn’t produce unintended behavior so it’s not worth throwing a warning on this type of thing

You are right that it can be both. However in a static-typed project, the absence of a ? generally implies that the value must not be nil, or that you are expecting a value in some way, shape, or form.
To put it simple, it’s more for verbose purposes than a functionaly one.

Depending on your team, project, or your own coding patterns, declaring whether a value should be non-nil is useful for debugging purposes. Let’s say you did this:

local foo: any = nil -- we declare it to be nil on instantiation, but we expect this to be a non-nil later
local bar: any? = nil

-- somewhere later in the code

local function doSomethingWithFoo(): any
    -- do something
    return localFoo :: any -- but somehow this returned nil
end

foo = doSomethingWithFoo()
foo.prop = "myProperty" -- this would error because `foo` is nil

This would tell you that somewhere in doSomethingWithFoo() had gone wrong and that it returned nil (which it shouldn’t). You are no longer left with guessing with your original design intention, and can now focus on fixing the bug.

Edit: as @Microwave_Toothpaste mentioned, using any in strictly typed code is generally a code smell. there may be situations where you need to use any as a catch-all when referencing a model with different children i.e. Model & { BasePart | Folder | AllOtherTypes }. generally speaking you should always declare the specific data type(s) you are expecting in a strictly typed program.

6 Likes

Using any in strictly typed code is bad practice because of situations like this.

1 Like

If you use strict typing in your code, you should avoid ever using the any type. any tells the type solver that you don’t care about that object’s type, effectively an “opt-out” of the type system altogether. Wherever you can use any, you should use unknown. unknown cannot be used as another type, unlike any, forcing you to perform type refinements before the unknown value can be used. This is generally preferable in most situations.

Appending a ? to a type makes the type nullable. In practice this creates a union between the type and nil:

T? = T | nil

When you use any, it is functionally the same as unknown, which is a union of all types. Therefore, any is already nullable, since unknown is nullable. Practically, using ? is generally just for function parameters to be marked as optional, you shouldn’t really be using it for a variable.

tldr just dont use any, use unknown

1 Like

There’s also an exception when variables are defined which lets them be assigned nil even if they are marked as a specific type. This code gives me a type warning on line 4. It doesn’t have a problem with line 2.

--!strict
local a : number = nil
 a = 34
 a = nil

Type Error: (4,6) Type ‘nil’ could not be converted into ‘number’

I suppose this is so that a local a : number; declaration won’t throw an error even though it doesn’t initialize it with a number value.

thank you guys! appreciate all answers

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