Currently, the only way to denote a nilable value as non-nil in Luau is to cast the value to its non-nil variant. In some cases, there are guaranteed scenarios where a nilable value is known to be non-nil by the developer.
I propose adding some symbol, say !
, that can be used to quickly tell the type checker that a value is not nil. Effectively, it is a negation to the ?
operator: Where ?
declares a value as potentially nil, !
can be used to declare that a nilable value is non-nil.
This change would improve code cleanliness, especially for cases where something’s return value is marked as nilable, but at the time it is called the developer knows it is non-nil. This problem becomes exponentially worse as nested types are encountered, or otherwise long chains of references.
The primary purpose of this change is to avoid using if statements, because as far as I’m aware, Luau casts are exclusively for the type checker right now, and so live code processing doesn’t take time figuring out a condition when running these lines, that is, it’s effectively identical to flat out ignoring nil value warnings. It’s also quite messy to have a chain of if statements for single-line operations that !
would benefit.
A simple example might be a reference to a Motor6D:
-- This...
local myJoint: Motor6D = ... -- Just for something usable.
-- Pretend Part0 is undeniably populated with a valid reference.
print((myJoint.Part0::BasePart).Name) -- Without the cast, this complains about
-- nullability of Part0.
-- Turns into...
print(myJoint.Part0!.Name) -- This functions identically, quietly casting
-- Part0 to its non-nullable counterpart.
Or more extremely, some nested types:
type MyType = {
Other: MyOtherType?
}
type MyOtherType = {
Thing: Instance?
}
local data: MyType = {
Other = { Thing = workspace }
}
-- This complains about the value being potentially nil
print(data.Other.Thing.Name)
-- ...And can be silenced with
print(((data.Other::MyOtherType).Thing::Instance).Name)
-- ...Which is a mess. But using this feature request, it can become
print(data.Other!.Thing!.Name)