Я знаю, что вы сказали, что хотели бы избежать двух занятий, потому что не хотели подразумевать, что они разные. Запрос, который в некоторых случаях не имеет значения, не делает его вредным. Вы все еще можете использовать один класс с единственной реализацией request
, которую вы используете только тогда, когда это требуется. Если вам действительно нужно указать, что request
отсутствует, вам придется создать отдельный тип. Вы можете достичь семантически того, что вы хотите, без каких-либо антипаттернов, используя фабричный шаблон и условные типы
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'); // is an error
У вас все еще есть несколько классов и интерфейсов со строгой системой типов, но единственный способ создать те объекты, которые подразумевает последовательную цель, если не последовательную реализацию. И поскольку оба расширяют один универсальный интерфейс c, вы можете передавать любой тип как один ZMQType. Вам просто нужно убедиться, что вы проверяете правильность наличия метода request
, прежде чем пытаться его использовать.
function testZMQImplementation(z: ZMQBus) {
if (z.request) {
z.request('testing')
}
}
testZMQImplementation(zmqObj);
testZMQImplementation(zmqObj1);