mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-23 06:10:02 +08:00
98 lines
2.4 KiB
TypeScript
98 lines
2.4 KiB
TypeScript
// Method calls through interface-typed receivers whose implementations are
|
|
// program classes: number, string and boolean arguments and results, void
|
|
// methods (including implementations that return a value), methods
|
|
// that read and write `this`, thrown errors, and object-literal
|
|
// implementations of the same interface.
|
|
interface Shape {
|
|
area(): number;
|
|
scale(k: number): number;
|
|
describe(prefix: string, loud: boolean): string;
|
|
grow(by: number): void;
|
|
}
|
|
|
|
class Circle implements Shape {
|
|
r: number;
|
|
constructor(r: number) {
|
|
this.r = r;
|
|
}
|
|
area(): number {
|
|
return 3 * this.r * this.r;
|
|
}
|
|
scale(k: number): number {
|
|
return this.r * k;
|
|
}
|
|
describe(prefix: string, loud: boolean): string {
|
|
const text = `${prefix} circle r=${this.r}`;
|
|
return loud ? text.toUpperCase() : text;
|
|
}
|
|
grow(by: number): void {
|
|
this.r += by;
|
|
}
|
|
}
|
|
|
|
class Rect implements Shape {
|
|
w: number;
|
|
h: number;
|
|
constructor(w: number, h: number) {
|
|
this.w = w;
|
|
this.h = h;
|
|
}
|
|
area(): number {
|
|
return this.w * this.h;
|
|
}
|
|
scale(k: number): number {
|
|
if (k < 0) throw new RangeError(`negative scale ${k}`);
|
|
return (this.w + this.h) * k;
|
|
}
|
|
describe(prefix: string, loud: boolean): string {
|
|
return `${prefix} rect ${this.w}x${this.h}${loud ? "!" : ""}`;
|
|
}
|
|
// A void interface method may be implemented by one that returns a value.
|
|
grow(by: number): number {
|
|
this.w += by;
|
|
this.h += by;
|
|
return this.w * this.h;
|
|
}
|
|
}
|
|
|
|
const literal: Shape = {
|
|
area: () => 1,
|
|
scale(k: number): number {
|
|
return k + 0.5;
|
|
},
|
|
describe(prefix: string, loud: boolean): string {
|
|
return `${prefix} literal ${loud}`;
|
|
},
|
|
grow(by: number): void {
|
|
console.log("literal grows", by);
|
|
},
|
|
};
|
|
|
|
function report(s: Shape): string {
|
|
return `${s.area()} ${s.scale(2)} ${s.describe("a", false)} ${s.describe("b", true)}`;
|
|
}
|
|
|
|
const shapes: Shape[] = [new Circle(1), new Rect(2, 3), literal];
|
|
for (const s of shapes) console.log(report(s));
|
|
|
|
for (const s of shapes) {
|
|
s.grow(1);
|
|
console.log(s.area());
|
|
}
|
|
|
|
let total = 0;
|
|
for (let i = 0; i < 1000; i++) total += shapes[i % 3]!.scale(i & 7);
|
|
console.log(total);
|
|
|
|
try {
|
|
shapes[1]!.scale(-1);
|
|
} catch (error) {
|
|
console.log((error as Error).name, (error as Error).message);
|
|
}
|
|
|
|
// Mutation through the interface is visible on the instance.
|
|
const c = new Circle(5);
|
|
const asShape: Shape = c;
|
|
asShape.grow(2);
|
|
console.log(c.r, asShape.area(), asShape.describe("c", false));
|