Files
scriptc/tests/corpus/captured-class-refinement.ts
Chris Tate 06b03f06a9 Compose class references across unions and collections (#734)
* Compose class references across unions and collections

- Compare class, function and native references held in differently represented unions with `===`, `!==` and `Object.is` while preserving subclass identity, and refuse comparisons that a structural union arm leaves undecidable
- Keep subclass values intact through base-typed array and Set insertion spreads, `concat`, and inferred class-predicate `filter`/`find`/`findLast`, and allow checked class refinement of captured optional values with several class arms
- Split the sanitized compiler self-rebuild CI job at the IR boundary, after giving sort helpers distinct IR nodes so serialized and in-memory IR emit the same LLVM

* Keep compact comparisons for plain union arms

- Compare a plain operand with a union that already holds its type through the existing inline union comparison, preserving established parameter representations
- Update the coverage expectation for the accepted class refinement
2026-10-08 07:35:21 -05:00

44 lines
1.5 KiB
TypeScript

class Base { value = 1; }
class Child extends Base {
extra = 2;
read(): number { return this.value + this.extra; }
}
class Named { name = "named"; }
type Value = Base | Named | string;
function isChild(value: Value): value is Child { return value instanceof Child; }
function inspect(value: Value): number {
const keep = (): Value => value;
keep();
if (isChild(value)) {
value.extra += 3;
return value.read();
}
return -1;
}
function asserted(value: Value): number {
const keep = (): Value => value;
keep();
return (value as Child).read();
}
const child = new Child();
const values: Value[] = [child, new Named(), "text", new Base()];
for (const value of values) console.log(inspect(value));
console.log(asserted(values[0]));
for (const value of values) {
if (isChild(value)) console.log(value.extra, value.read(), value === child);
}
const selected = values.filter((value) => value instanceof Child);
console.log(selected[0] === child, selected[0]!.read());
console.log(values.find((value) => value instanceof Child) === child);
console.log(values.findLast((value) => value instanceof Child) === child);
const empty: Value[] = [];
console.log(empty.find((value) => value instanceof Child) === undefined);
const changed: Value[] = [child, new Child(), "text"];
const kept = changed.filter((value, index, array) => {
array[index] = "replaced";
return value instanceof Child;
});
console.log(kept.length, kept[0] === child, changed[0] === "replaced");
try { asserted(values[20]); } catch (error) { console.log(error instanceof TypeError); }