mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-02 07:43:42 +08:00
A class may implement a void interface method with a method that returns a value, and JavaScript passes that value on (`console.log(c.publish(m))`). The call now keeps the dispatch's untyped result, as a call through a non-generic void member already does, instead of replacing it with undefined: printing or interpolating it shows the value, and binding it to a void-typed name checks it.
66 lines
2.0 KiB
TypeScript
66 lines
2.0 KiB
TypeScript
// Calling a void generic method through an interface value that classes
|
|
// implement (the receiver is a checked-dynamic object, and the call
|
|
// dispatches by name to the class's erased method) discards the result, as
|
|
// JavaScript does, instead of converting it to `void`.
|
|
|
|
interface Message<T = unknown> {
|
|
content: string;
|
|
details?: T;
|
|
}
|
|
|
|
interface Channel {
|
|
name: string;
|
|
publish<T = unknown>(message: Message<T>): void;
|
|
count<T>(items: T[]): number;
|
|
}
|
|
|
|
const delivered: string[] = [];
|
|
|
|
class LogChannel implements Channel {
|
|
name: string;
|
|
constructor(name: string) {
|
|
this.name = name;
|
|
}
|
|
publish<T = unknown>(message: Message<T>): void {
|
|
delivered.push(`${this.name}:${message.content}:${message.details === undefined ? "-" : JSON.stringify(message.details)}`);
|
|
}
|
|
count<T>(items: T[]): number {
|
|
return items.length;
|
|
}
|
|
}
|
|
|
|
class LoudChannel extends LogChannel {
|
|
publish<T = unknown>(message: Message<T>): void {
|
|
super.publish({ content: message.content.toUpperCase(), details: message.details });
|
|
}
|
|
}
|
|
|
|
const channels: Channel[] = [new LogChannel("quiet"), new LoudChannel("loud")];
|
|
for (const channel of channels) {
|
|
channel.publish({ content: "hello", details: [1, 2] });
|
|
channel.publish({ content: "bare" });
|
|
const result = channel.publish<string>({ content: "typed", details: "x" });
|
|
console.log(channel.name, result === undefined, channel.count(["a", "b", "c"]));
|
|
}
|
|
console.log(delivered.join(" | "));
|
|
|
|
// A class may implement the void member with a method that returns a value;
|
|
// JavaScript passes that value on.
|
|
class CountingChannel implements Channel {
|
|
name = "counting";
|
|
sent = 0;
|
|
publish<T = unknown>(message: Message<T>): number {
|
|
this.sent++;
|
|
return message.content.length;
|
|
}
|
|
count<T>(items: T[]): number {
|
|
return items.length * 2;
|
|
}
|
|
}
|
|
|
|
const counted: Channel[] = [new CountingChannel(), new LogChannel("plain")];
|
|
for (const channel of counted) {
|
|
console.log(channel.name, channel.publish({ content: "four" }));
|
|
console.log(`sent ${channel.publish<number>({ content: "again", details: 2 })}`);
|
|
}
|