mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-21 05:50:55 +08:00
- 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.
70 lines
2.5 KiB
TypeScript
70 lines
2.5 KiB
TypeScript
// Destructuring now lowers defaults in every position (tuple, array with
|
|
// the bounds test, record fields, nested patterns, whole-pattern and
|
|
// rest-pattern parameters, getter results), rest in every declaration
|
|
// position (array slices, tuple tails pack fresh, object rest copies the
|
|
// unconsumed fields — class instances included, corpus 2539),
|
|
// assignment-position patterns over static sources — record AND
|
|
// class-instance, with nested patterns, property/element targets, and
|
|
// defaults (corpus 2536-2538) — and for-of expression heads. What stays
|
|
// fenced is the honest residue: METHOD extraction over class instances
|
|
// (a detached method loses its receiver), rest whose packed type is not
|
|
// a plain record (a class of methods only packs '{}' — 'unknown'),
|
|
// rest that would copy a NON-PUBLIC field (JS copies it; the rest type
|
|
// cannot name it), setter-only properties, union sources (narrow
|
|
// first), object patterns over arrays, index-signature rest packing,
|
|
// defaults on NESTED assignment targets (no single binding type to
|
|
// test against), and assignment targets with no static write form.
|
|
|
|
class C {
|
|
f = 1;
|
|
describe(): string {
|
|
return `f=${this.f}`;
|
|
}
|
|
set onlyIn(v: number) {
|
|
this.f = v;
|
|
}
|
|
}
|
|
const { describe } = new C(); // method extraction keeps the fence
|
|
console.log(describe());
|
|
const { f, ...restOfC } = new C(); // rest over a class instance keeps the fence
|
|
console.log(f, Object.keys(restOfC).length);
|
|
const { onlyIn } = new C(); // tsc types the setter-only read; the fence names it
|
|
console.log(onlyIn);
|
|
|
|
interface E1 {
|
|
kind: "one";
|
|
b: string;
|
|
count: number;
|
|
}
|
|
interface E2 {
|
|
kind: "two";
|
|
b: string;
|
|
label: string;
|
|
}
|
|
function fromUnion(u: E1 | E2): string {
|
|
const { b } = u; // union source: narrow first
|
|
return b;
|
|
}
|
|
console.log(fromUnion({ kind: "one", b: "s", count: 1 }));
|
|
|
|
const xs = [1, 2, 3];
|
|
const { length: len } = xs; // object patterns over arrays keep the fence
|
|
console.log(len);
|
|
|
|
const indexed: Record<string, number> = { a: 1 };
|
|
const { ...allOfIt } = indexed; // index-signature rest needs overflow packing
|
|
console.log(allOfIt["a"]);
|
|
|
|
const holder = { inner: { v: 1 } };
|
|
let sink = 0;
|
|
({ inner: { v: sink } = { v: 2 } } = holder); // a DEFAULT on a nested assignment target keeps the fence
|
|
console.log(sink);
|
|
|
|
class WithPrivate {
|
|
pub = 1;
|
|
private hidden = 2;
|
|
also = 3;
|
|
}
|
|
const { pub, ...restOfPriv } = new WithPrivate(); // JS copies 'hidden' into the rest object; the rest type cannot name it
|
|
console.log(pub, JSON.stringify(restOfPriv));
|