mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-02 08:35:07 +08:00
65 lines
2.1 KiB
TypeScript
65 lines
2.1 KiB
TypeScript
// Structural width subtyping: a record (or record array) flowing into a
|
|
// strict field-subset slot reshapes by copying the subset of fields.
|
|
// Everything here is read-after-narrow, where the copy is observationally
|
|
// identical to Node's aliasing (the divergence is SEMANTICS.md 35).
|
|
type ModelEntry = {
|
|
id: string;
|
|
name: string;
|
|
released: number;
|
|
};
|
|
|
|
const models: ModelEntry[] = [
|
|
{ id: "m1", name: "One", released: 2024 },
|
|
{ id: "m2", name: "Two", released: 2025 },
|
|
];
|
|
|
|
// Array-into-array slot flow (the Pick display-table pattern).
|
|
function listIds(entries: { id: string }[]): string {
|
|
const ids: string[] = [];
|
|
for (const e of entries) ids.push(e.id);
|
|
return ids.join(",");
|
|
}
|
|
console.log(listIds(models));
|
|
|
|
// Single-record width flow, direct argument and initializer.
|
|
function describe(m: { id: string; released: number }): string {
|
|
return `${m.id}@${m.released}`;
|
|
}
|
|
console.log(describe(models[0]!));
|
|
const narrowed: { name: string } = models[1]!;
|
|
console.log(narrowed.name);
|
|
|
|
// Union slots: the coerced value wraps into the matching arm.
|
|
function maybeIds(entries?: { id: string }[]): number {
|
|
if (entries === undefined) return -1;
|
|
return entries.length;
|
|
}
|
|
console.log(maybeIds(models), maybeIds(undefined));
|
|
function oneOrNothing(m: { id: string } | undefined): string {
|
|
return m === undefined ? "none" : m.id;
|
|
}
|
|
console.log(oneOrNothing(models[0]), oneOrNothing(undefined));
|
|
|
|
// Fields with union types copy exactly (same field type, no re-tag).
|
|
type Task = { id: string; note: string | undefined; extra: number };
|
|
const tasks: Task[] = [
|
|
{ id: "t1", note: "hello", extra: 7 },
|
|
{ id: "t2", note: undefined, extra: 8 },
|
|
];
|
|
function notes(xs: { id: string; note: string | undefined }[]): void {
|
|
for (const t of xs) {
|
|
console.log(t.id, t.note === undefined ? "-" : t.note);
|
|
}
|
|
}
|
|
notes(tasks);
|
|
|
|
// Returns flow through the same slot coercion.
|
|
function firstNarrow(xs: ModelEntry[]): { id: string } {
|
|
return xs[0]!;
|
|
}
|
|
console.log(firstNarrow(models).id);
|
|
|
|
// Empty arrays reshape to empty arrays.
|
|
const none: ModelEntry[] = [];
|
|
console.log(listIds(none), maybeIds(none));
|