#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:
Эти два типа, о которых идет речь…
- Универсальный, когда вы вызываете
webSocket<T>()
- Значение, передаваемое в следующий
.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$
.
Комментарии:
1. да, в документации они одного типа. но в реализации ресурса websocket, который я использую, они имеют разные типы, поэтому во время выполнения мы ведем себя иначе, чем ожидалось, основываясь на документации / передаче одного общего
2. Хорошо — значит, использование
.multiplex
метода вместо.next
работы. я предполагаю, что причина путаницы, которая у меня была, заключалась в том, что использование.next
с сообщением о подписке работало, если тип был допустимым (сервер отвечал бы так, как было предсказано), но это сообщение было другого типа, чем то, которое отправил сервер. спасибо за помощь!