Files
scriptc/tests/corpus/2540-accessor-destructuring-defaults.ts
Chris Tate 385b0a9199 Promote destructuring assignment targets, class-instance sources, class rest, and accessor defaults to the static tier
- Destructuring assignment now takes nested patterns (`({ p: { q } } = src)`, `[[a], b] = t`) and property/element targets (`[c.x, box.vals[i]] = arr`, `({ a: rec.f } = o)`, rest into members) — receivers temp at their pattern position, JS's reference-before-read order; defaults on member targets test against the target's own type. Defaults on nested targets keep a named fence (no single binding type to test against).
- Class instances destructure in assignment position like they already did in declarations: field slots and getter calls per element via the same fieldGetExpr dispatch, defaults, renames, and member targets; methods and undeclared names keep their pointed fences.
- Rest over class-instance sources packs the remaining instance FIELDS into a fresh record (JS's CopyDataProperties copies own enumerable properties — never prototype methods/accessors, matching the checker's rest type), in declarations and assignments; non-public fields, runtime-provided chains (Error/EventEmitter/stream), and key orders the packed shape cannot reproduce fence instead of diverging.
- Defaults on destructured getter results now lower (record and class accessors alike), with the getter result temped so the default's undefined test never calls it twice; numeric-literal pattern keys (`const { 2: x } = o`) fold to JS's canonical property name.
- Corpus 2536-2540 pin the new forms byte-identically against Node on both backends; the destructuring-fences diagnostics program keeps the honest residue (method extraction, non-public rest fields, nested-target defaults, index-signature rest).
- The ts7 order-parity baseline re-record backfills the entries the released file was missing (2490-2500 included) alongside the new fixtures; no existing entry changed.
2026-07-23 17:27:25 -05:00

57 lines
1.4 KiB
TypeScript

// Accessor properties under destructuring: the element's read IS one
// getter call at the element's pattern position, and a DEFAULT applies
// to the getter's result exactly like a data field's (undefined fires
// it, values don't, null never does).
let pulls = 0;
const counter = {
get next(): number {
pulls += 1;
return pulls * 10;
},
base: 5,
};
const { next, base } = counter;
console.log(next, base, pulls);
const { next: second } = counter;
console.log(second, pulls);
// Defaults on getter results: undefined fires, a value does not.
let hits = 0;
const sometimes = {
get maybe(): number | undefined {
hits += 1;
return hits > 1 ? hits : undefined;
},
};
const { maybe: firstPull = -1 } = sometimes;
const { maybe: secondPull = -2 } = sometimes;
console.log(firstPull, secondPull);
// The default expression itself stays lazy: it only evaluates when the
// getter answered undefined.
let defaultRuns = 0;
function fallback(): number {
defaultRuns += 1;
return 1000;
}
const supplied = {
get v(): number | undefined {
return 42;
},
};
const { v = fallback() } = supplied;
console.log(v, defaultRuns);
// Class accessors take defaults the same way.
class Lazy {
seed?: number;
get grown(): number | undefined {
return this.seed;
}
}
const early = new Lazy();
const { grown: g1 = -9 } = early;
early.seed = 8;
const { grown: g2 = -9 } = early;
console.log(g1, g2);