различные типы для rxjs websocketsобъекта на основе запроса/ответа (следующий тип msg, подписаться на тип msg), но допускается только один универсальный

#typescript #generics #types #websocket #rxjs

Вопрос:

я работаю webSocket с rxjs, и у меня проблема с аргументом универсального типа.

в документации по API websocket говорится, что сообщения запроса и ответа имеют разные свойства, но универсальный для WebSocketSubject принимает только один тип.

итак, у нас есть что-то вроде:

 import { webSocket } from "rxjs/webSocket";

const subject = new webSocket<MessageType>('wss://something');

subject.subscribe({
    error: err => {
        throw err;
    },
    next: msg /* this is of type MessageType, but the actual object is not the same type as what is input into `subject.next` */ => {
        console.log(msg); // outputs something like: { anotherProperty: "anotherValue" }
    },
    complete: () => {
        done();
    }
}); 

// but this argument is also of type MessageType
subject.next({
    testProperty1: "test value 1"
});

 

проблема в том, что тип msg в next свойстве subscribe метода, но также subject.next один и тот же, в то время как в документации указаны разные типы (объекты имеют разные свойства) для входных и выходных сообщений.

теперь, конечно, можно было бы использовать any или создать тип объединения с необязательными параметрами, чтобы все работало, но было бы более идеальным иметь возможность указать один тип для входных сообщений и другой для выходных сообщений. может ли это быть легко достигнуто с помощью реализации rxjs webSocket или мне нужно написать оболочку или что-то еще, чтобы сделать это более чистым?

в идеале то, что я хотел бы сделать, было бы чем-то вроде следующего (хотя, конечно, в настоящее время я не вижу, что это возможно):

 
const subject = new webSocket<RequestMessageType, ResponseMessageType>('wss://something');

 

Ответ №1:

Эти два типа, о которых идет речь…

  1. Универсальный, когда вы вызываете webSocket<T>()
  2. Значение, передаваемое в следующий .next<T>()

…они точно такого же типа.

Общий тип, который вы определяете при создании экземпляра T , — это тип сообщения, которое будет получено из веб-сокета при подписке.

WebSocketSubject является расширением a Subject , которое включает в себя такие методы, как .next() . Это означает WebSocketSubject.next() , что делает то же самое Subject.next() , что и выдает следующее значение типа T для всех подписчиков RxJS. Вот почему .next() метод имеет тот же T общий вид.

Способ WebSocketSubject , позволяющий отправлять сообщения (которые имеют тип any ) в WS, заключается в том, что вы объявляете свои общедоступные наблюдаемые объекты, которые будут предназначены для подписчиков.

 const wsSubject = webSocket<MessageType>('wss://something');

const wsMessages$ = wsSubject.multiplex(
  () => {} , // send message to WS server to start 
  () => {} , // send message to WS server to stop 
  (message) => true // filter messages by condition
);
 

Эти сообщения о запуске и остановке автоматически выполняются по мере того, как подписчики начинают или заканчивают подписку wsMessages$ .

Ссылка: https://rxjs.dev/api/webSocket/WebSocketSubject

Комментарии:

1. да, в документации они одного типа. но в реализации ресурса websocket, который я использую, они имеют разные типы, поэтому во время выполнения мы ведем себя иначе, чем ожидалось, основываясь на документации / передаче одного общего

2. Хорошо — значит, использование .multiplex метода вместо .next работы. я предполагаю, что причина путаницы, которая у меня была, заключалась в том, что использование .next с сообщением о подписке работало, если тип был допустимым (сервер отвечал бы так, как было предсказано), но это сообщение было другого типа, чем то, которое отправил сервер. спасибо за помощь!