Runtime Mismatch
LuaTuple is a JavaScript array at runtime, so a truthiness check does not match Luau’s first-value behavior.
Disallow using LuaTuple in conditional expressions.
In roblox-ts, a LuaTuple represents multiple return values from Luau. Using a LuaTuple directly in a conditional
is almost always a bug. At runtime it’s an array, so the value is always truthy in JavaScript/TypeScript, even if the
first Luau return value is false or nil.
This rule reports LuaTuple values in if, while, do...while, and for conditions, conditional expressions,
logical expressions, and !tuple checks. It also reports declarations, assignments, and for...of bindings that keep
the tuple as a single value instead of destructuring it.
The rule is fixable. For condition-style checks it adds [0]. For declarations, assignments, and for...of, it wraps
the binding in array destructuring, for example const result = getTuple() becomes const [result] = getTuple().
It also handles IterableFunction types that yield LuaTuple values in for...of loops.
[0].const [success, data] = getTuple() instead of storing the whole tuple.if (success) { ... } or another explicit check.for...of. If the iterable yields tuples, destructure each item as it comes out.A tuple value is always truthy, even when the first return value is falsey.
const result = getLuaTuple();
// ❌ Always true! Even if the first return is false.if (result) { print("This always prints");}Destructure and check the specific value you care about.
// ✅ Destructuring (Recommended)const [success, data] = getLuaTuple();if (success) { print("Action succeeded");}
// ✅ Explicit indexingif (getLuaTuple()[0]) { print("Value exists");}Runtime Mismatch
LuaTuple is a JavaScript array at runtime, so a truthiness check does not match Luau’s first-value behavior.
Silent Failures
Code can take the wrong branch and keep running without an obvious error.
Type Clarity
Destructuring makes it clear which tuple value you are actually using.