I want the code of my own classes for rooms look and work similar both on the client and on the server.
In a Colyseus server the function creating rooms, Server.define, takes a custom room class as argument. That custom class has to extend the server's room class, for example export class MyServerRoom extends Room<MyState>, and is instantiated by Server.define on demand.
export class MyServerRoom extends Room<MyState> { /* ... */ }
Server.define("myserverroom", MyServerRoom, options)
In a Colyseus client the functions creating rooms, Client.joinOrCreate or Client.consumeSeatReservation or the others, do not take a custom class as argument. Instead they instantiate and return (a promise to) the client's room class, Room<MyState>. As far as I know one cannot simply cast this to a custom room class which extends the client's room class.
Client.consumeSeatReservation<MyState>(roomReservation, MyState)
.then((room: Room<MyState>) => { /* ... */ }
The code in my first post tries to overload the client's internal method createRoom to instantiate a custom room class (extending the client's room class), which is then cast "down" to the client's room class and which is then cast "back up" to the custom room class after it is returned by Client.joinOrCreate or Client.consumeSeatReservation.
I assume what I want is Client.joinOrCreate or Client.consumeSeatReservation taking a custom room class (extending the client's room class) as argument and returning an instance of that class (instead of the plain client's room class).
Another thing about similarity: The server's room class has its "room lifecycle" methods, for example onCreate or onLeave, which can be overloaded in a custom class. The client's room class does not have those, but instead has member variables which can be set to callback functions, for example onStateChange or onLeave. That simply is not similar in my opinion - but probably it is like that for good reasons - reasons I do not understand yet.