-
Notifications
You must be signed in to change notification settings - Fork 196
Fix types for the echo library #403
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Will have a look at the |
Hey Dennis! Would need to lean on your expertise here. I am not a TS expert by any means. Feel free to push through the errors and proceed. Would be happy to get this merged. Please mark as ready for review when the changes have been made. |
Ok, so regarding the StyleCI issues, still not sure. It recommends changing the coding style for areas that already were styled like this, but I am happy to update this as well to satisfy StyleCI. A few things here: Due to the nature of the code a few more things needed to be generic and since TypeScript is TypeScript, once you started with generics it wants you to go all the way. Most of the changes are only types, these should not have an effect on any logic of Echo. However a few other changes were necessary: 1. Exception 2. Public Channels 3. NullEncryptedPrivateChannel 4. 5. Tests 6. Function Broadcaster In my understanding the function broadcaster enables users to write any kind of function that creates a custom connector and Echo will then use this connector. In this case I don't think the @taylorotwell I am not a TypeScript Typesystem expert as well but from my tests the functions now return the types correctly and carry them on through different classes. Would love to hear some feedback from some more experienced type enthusiasts if anyone has the time for it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Going to start with this one and add more as I continue to review.
The use of generics for channels is not necessary thankfully. By using this
as the return type we can get a really nice fluent API with good types an no overhead. It automatically types it as the most derived type automatically.
Example to apply to all channel code:
abstract class Base {
abstract someMethod(): this;
anotherMethod(): this {
// Base logic
return this;
}
}
class FirstLevel extends Base {
someMethod(): this {
// Logic specific to FirstLevel
return this;
}
firstLevelMethod(): this {
// Logic specific to FirstLevel
return this;
}
}
class SecondLevel extends FirstLevel {
someMethod(): this {
return this;
}
firstLevelMethod(): this {
return this;
}
secondLevelMethod(): this {
// Logic specific to SecondLevel
return this;
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will double check this tomorrow, but that should help clean a lot of this up to be more clean and avoid generics as much as we can.
src/connector/connector.ts
Outdated
import { Channel, PresenceChannel } from './../channel'; | ||
|
||
export abstract class Connector { | ||
export abstract class Connector<TPublic, TPrivate, TPresence> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can make these a little more helpful.
abstract class Connector<
TPublic extends Channel,
TPrivate extends Channel,
TPresence extends Channel & PresenceChannel
>
This gives us compile time errors if we try to call connector with classes that aren't extensions of a channel.
Also ensures that the Presence generic implements the interface.
src/channel/presence-channel.ts
Outdated
@@ -3,24 +3,24 @@ import { Channel } from './channel'; | |||
/** | |||
* This interface represents a presence channel. | |||
*/ | |||
export interface PresenceChannel extends Channel { | |||
export interface PresenceChannel<T> extends Channel<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An interface can also use the this
return so that we can avoid generics.
Drafting while this is actively worked on. Please mark as ready for review when you want me to take another look. |
@wking-io Hey, many thanks! I didn't think of simply returning the current instance as a type, this definitely cleans up a lot of that generic mess. Most methods now return For the connector I used We also could specify that a function broadcaster must return |
Happy to be of assistance! Everything else is looking great 🫡 |
Ok, most of the generics could be removed, as well as other intermediate classes that were necessary for the "generic solution". Much cleaner now. |
This looks to have led to an (unintended?) breaking change. Our old code for the broadcaster was just Update: it was fixed in #404 |
For anyone running into ts generic decleration issues, I found adjusting the below worked well for me in my types/index.d.ts file
|
I am using echo in a TypeScript project and I have to mark a lot of function calls with
// @ts-ignore
since the library uses types that don't always refer to the actual type being used.The whisper function for example spits out a type error, since the
private()
-function has the abstractChannel
as a return type.Channel
however doesn't have a whisper function.I have made some changes so the Echo class is more generic based on what is passed as a
broadcaster
in the options. I don't know if this is the best or the most elegant way to specify the types but with these changes the functions actually return the types they are supposed to:I split the PR in separate commits to better understand the changes.
encryptedPrivate()
function with the socket.io broadcaster. This would throw an Error in any way, the addition is only to satisfy TypeScript.any
sinceleaveAllChannels()
expects achannels
property on the connector that the baseConnector
doesn't have.There are some other thing like when calling the following:
the
listen()
function returns aPusherChannel
again while it should be aPusherPrivateChannel
. But I wanted to see if there is actually any interest in these changes before tackling this one.