It was mentioned that avoiding two classes to prevent implying differences between them. However, the insignificance of a request in certain scenarios does not equate to harm. A solution could involve utilizing a single class with a conditional implementation of request
, where it is only utilized when necessary. If the absence of request
must be explicitly stated, a separate type can be created. By employing a factory pattern and conditional types, semantic clarity can be achieved without falling into any anti-patterns.
type ZmqTypes = "REQUEST" | "NOREQUEST";
interface ZMQBus {
open: () => void;
close: () => void;
request?: (msg: any) => void;
type: ZmqTypes;
port: number;
}
interface ZMQBusR extends ZMQBus {
request: (msg: any) => void;
}
interface ZMQBusNoR extends Omit<ZMQBus, "request"> {}
class GenericZMQBus implements ZMQBus {
socket:any
port:number
constructor(type:string, port:number) {
this.socket = zmq.socket(type)
this.port = port
}
open(): void {
this.socket.connect("tcp://localhost:" + this.port)
this.socket.on("message", function(reply : any) {
console.log("Received reply : " + reply.toString());
})
}
close(): void {
this.socket.close();
}
}
class ZMQBusWithRequest extends GenericZMQBus implements ZMQBusR {
request(msg : any) {
console.log(msg);
}
}
function createZMQBus<T extends ZmqTypes>(type: T, port: number) : T extends "REQUEST" ? ZMQBusR : ZMQBusNoR {
if (type === "REQUEST") {
return new ZMQBusWithRequest(type, port) as unknown as T extends "REQUEST" ? ZMQBusR : ZMQBusNoR;
}
return new GenericZMQBus(type, port) as unknown as T extends "REQUEST" ? ZMQBusR : ZMQBusNoR;
}
const zmqObj = createZMQBus("REQUEST", 999);
const zmqObj1 = createZMQBus("NOREQUEST", 999);
zmqObj.request('hello');
zmqObj1.request('error'); // results in an error
This approach retains multiple classes and interfaces within a strict type system, but offers a unified method for creating objects that signifies a consistent purpose, even if implementations vary. Both extensions of a shared generic interface enable passing either type as a single ZMQType. It is essential to verify the presence of the request
method before usage.
function testZMQImplementation(z: ZMQBus) {
if (z.request) {
z.request('testing')
}
}
testZMQImplementation(zmqObj);
testZMQImplementation(zmqObj1);