Files
scriptc/tests/corpus/2538-destructuring-assign-class-source.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

67 lines
1.4 KiB
TypeScript

// Destructuring assignment FROM class instances: field reads, getter
// calls at the element's pattern position, inherited members, defaults
// against the target's own type, renames, and member targets fed from a
// class source.
class Base {
root = "r";
}
class Item extends Base {
id = 7;
label = "seven";
get loud(): string {
return this.label.toUpperCase();
}
}
const item = new Item();
let id = 0;
let label = "";
({ id, label } = item);
console.log(id, label);
// Renames and getters.
let shout = "";
let from = "";
({ loud: shout, root: from } = item);
console.log(shout, from);
// Defaults from undefined-armed class fields.
class Sparse {
hit?: number;
miss?: number;
constructor() {
this.hit = 3;
}
}
let hit = -1;
let miss = -1;
({ hit = -10, miss = -20 } = new Sparse());
console.log(hit, miss);
// A class source feeding MEMBER targets.
const sink = { a: 0, b: "" };
({ id: sink.a, label: sink.b } = item);
console.log(sink.a, sink.b);
// Getters run ONCE per element, at the element's position.
const order: string[] = [];
class Tracked {
get first(): number {
order.push("first");
return 1;
}
get second(): number {
order.push("second");
return 2;
}
}
let f = 0;
let sec = 0;
({ second: sec, first: f } = new Tracked());
console.log(order.join(","), f, sec);
// Expression-position class-source assignment keeps the RHS value.
let again = 0;
const same = ({ id: again } = item);
console.log(again, same.label);