mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-29 07:04:09 +08:00
`let f: T; f = (n) => ... f(n - 1)` at module scope threw "Cannot access 'f' before initialization": a function-typed (pointer-guarded) binding kept the null-pointer TDZ test on its writes, but the declaration already initialized it (to undefined) when it ran. Such bindings now carry the existing initialization flag: the declaration sets it, writes that can run earlier check it, and writes no longer test the empty pointer. A write that really precedes the declaration still throws. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
47 lines
1.3 KiB
TypeScript
47 lines
1.3 KiB
TypeScript
// A module-scope `let` declared without an initializer is initialized (to
|
|
// undefined) where the declaration runs, so a later assignment of a closure
|
|
// that calls the binding itself is an ordinary write.
|
|
type Step = (n: number) => number;
|
|
|
|
// A write that runs before the declaration is still in the dead zone.
|
|
function early(): void {
|
|
late = () => 1;
|
|
}
|
|
try {
|
|
early();
|
|
} catch (e) {
|
|
console.log((e as Error).name, (e as Error).message);
|
|
}
|
|
let late: () => number;
|
|
late = () => 2;
|
|
early();
|
|
console.log(late());
|
|
|
|
let countdown: Step;
|
|
countdown = (n) => (n <= 0 ? 0 : 1 + countdown(n - 1));
|
|
console.log(countdown(5));
|
|
|
|
let log: (s: string) => void;
|
|
log = (s) => {
|
|
if (s.length < 3) log(s + "!");
|
|
else console.log(s);
|
|
};
|
|
log("a");
|
|
|
|
// Reassignment and assignment from a function body after the declaration.
|
|
let pick: (xs: number[]) => number;
|
|
function install(largest: boolean): void {
|
|
pick = largest ? (xs) => Math.max(...xs) : (xs) => Math.min(...xs);
|
|
}
|
|
install(true);
|
|
console.log(pick!([3, 9, 4]));
|
|
install(false);
|
|
console.log(pick!([3, 9, 4]));
|
|
|
|
// Mutual recursion through two such bindings.
|
|
let isEven: (n: number) => boolean;
|
|
let isOdd: (n: number) => boolean;
|
|
isEven = (n) => (n === 0 ? true : isOdd(n - 1));
|
|
isOdd = (n) => (n === 0 ? false : isEven(n - 1));
|
|
console.log(isEven(10), isOdd(7), isEven(3));
|