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”?
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
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.
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.
Using any in strictly typed code is bad practice because of situations like this.
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
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.

