mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-23 06:10:02 +08:00
A for-of loop over an array whose own facts show a hole or a stored undefined binds T | undefined, and the typed parameters, locals, record fields and Math arguments it reaches widen to hold it. Loops over arrays the element-state analysis proves free of holes read each element directly, without a per-element state test. Object literals built from a missing-element read keep the property as undefined in shorthand and long form, through spreads, nested records, arrays of records, annotated locals and literal arguments to typed parameters.
39 lines
1.2 KiB
TypeScript
39 lines
1.2 KiB
TypeScript
// Structural refinements still need a named fence for multi-value storage.
|
|
// The class refinement below is accepted through a checked identity-preserving view.
|
|
type Item = { rect?: { width: number } };
|
|
|
|
function hasRect(item: Item | string): item is Item & { rect: { width: number } } {
|
|
return typeof item !== "string" && item.rect !== undefined;
|
|
}
|
|
|
|
function recordWidths(items: (Item | string)[]): void {
|
|
for (const item of items) {
|
|
if (hasRect(item)) console.log(item.rect.width);
|
|
}
|
|
}
|
|
|
|
class Animal {
|
|
name: string;
|
|
constructor(name: string) { this.name = name; }
|
|
}
|
|
class Dog extends Animal {
|
|
bark(): string { return this.name; }
|
|
}
|
|
|
|
function isDog(animal: Animal | string): animal is Dog {
|
|
return typeof animal !== "string" && animal instanceof Dog;
|
|
}
|
|
|
|
function classNames(animals: (Animal | string)[]): void {
|
|
for (const animal of animals) {
|
|
if (isDog(animal)) console.log(animal.bark());
|
|
}
|
|
}
|
|
|
|
recordWidths([{ rect: { width: 1 } }, "plain"]);
|
|
classNames([new Dog("dog"), "plain"]);
|
|
// A hole keeps the loop binding optional, so its refined read meets the fence.
|
|
const pending: (Item | string)[] = ["plain"];
|
|
pending[2] = { rect: { width: 2 } };
|
|
recordWidths(pending);
|