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.
Closures capture
letloop variables by final value, not per iteration. Standard TypeScript gives eachfor (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
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.