When you're looking for a quick solution, the answer is simple: use const
.
for (const foobar of foobars) {
if (foobar.type === "foo") {
console.log(foobar.foo); // fb is Foo
logFoo(foobar); // OK
console.log(numbers.filter(x => x < foobar.foo)); // Property 'foo' does not exist on type 'Foobar'
}
}
A const
variable, also known as 'final' in Java, cannot be reassigned. This provides strong guarantees. Within the if
statement, we can be absolutely certain that the value of foobar
is of type Foo
. Since it will never change, this information holds true within any closures inside the if
statement, giving us the expected behavior.
Now let's talk about let
.
for (let foobar of foobars) {
if (foobar.type === "foo") {
console.log(foobar.foo); // fb is Foo
logFoo(foobar); // OK
console.log(numbers.filter(x => x < foobar.foo)); // Property 'foo' does not exist on type 'Foobar'
}
}
A let
-bound variable is mutable. TypeScript understands that within the if
statement, the value hasn't changed. However, when passed to a closure, there is a risk of it being modified elsewhere in the codebase. The closure makes the safest assumption possible by preserving the original type of the let
-bound variable.
In the specific example mentioned, TypeScript could potentially infer that our foobar
remains unchanged given its limited scope within a for
loop without reassignments. But instead of delving deep into these specifics, TypeScript chooses caution.
If you do anticipate modifying the variable later but wish to capture its current value rather than the variable itself, you have the option to create a new const
-bound variable for that purpose.
for (let foobar of foobars) {
if (foobar.type === "foo") {
const newFoobar = foobar;
console.log(numbers.filter(x => x < newFoobar.foo)); // Property 'foo' does not exist on type 'Foobar'
}
}
At the point of creating newFoobar
, it retains the type Foo
that foobar
has. As a const
, newFoobar
always remains as type Foo
. Security is assured when capturing newFoobar
(as type Foo
) within a closure.