Skip to content

[compiler] Closures capture let loop variables by final value, not per iteration #11563

Description

Closures capture let loop variables by final value, not per iteration. Standard TypeScript gives each for (let i ...) iteration a fresh binding; static TypeScript shares one binding, so every closure sees the loop's final value.

Repro: https://makecode.com/_1m7JkiYRK5Yw

const fns: (() => number)[] = []
for (let i = 0; i < 4; i++) {
    fns.push(() => i)
}
console.log(fns.map(f => f()).join(","))
// standard TypeScript: 0,1,2,3
// static TypeScript:   4,4,4,4

Confirmed on the simulator backend and on a micro:bit V2; both backends agree, so this is emitter-level scoping, not a backend bug. Workaround: capture through a function parameter (function mk(v: number) { return () => v }), which binds per call.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions