Skip to content
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

Class support? #3

Open
SrZorro opened this issue Jun 25, 2018 · 9 comments
Open

Class support? #3

SrZorro opened this issue Jun 25, 2018 · 9 comments

Comments

@SrZorro
Copy link

SrZorro commented Jun 25, 2018

I'm trying to use this library to add types to my class that extends from EventEmitter, but I can't find a way to make it work with my example:

import StrictEventEmitter from "strict-event-emitter-types";
import { EventEmitter } from "events";

interface IEvents {
    onValueSended: string;
    ready: void;
}

//    [ts] Class 'MyClass' incorrectly
//    implements interface 'IEvents'.
//    Property 'onValueSended' is missing     [ts] Generic type 'StrictEventEmitter'
//    in type 'MyClass'.                      requires between 2 and 5 type arguments.
//    ↓                                       ↓
class MyClass extends EventEmitter implements StrictEventEmitter<EventEmitter IEvents> {
    constructor() {
        super();
        // Some long work...
        this.emit("ready");
    }
    sendValue() {
        this.emit("onValueSended", "Hello!");
    }
}

const myClass = new MyClass();
myClass.on("onValueSended", x => x);
myClass.sendValue(); // ← [ts] Property 'sendValue' does not exist on type 'MyClass'.
myClass.on("ready", () => {/* Do stuff... */ });

Also, there is a way to make it work with computed properties? Lets say I want to have an event called something like

interface IEvents {
    /^action_.+/: void;
    init: number;
}
/* class MyClass etc... */
myClass.on("action_jump", () => {})
myClass.on("action_dance", (x) => {}) //Error, no payload
myClass.on(/^action_.+/, () => {}) //Match all action events
myClass.on("jump_action", () => {}) //Error
myClass.on("action_", () => {}) //Error
myClass.on("init", (x) => {})

I supose this last one is related with microsoft/TypeScript#6579 and can't be fixed by this library.

@krzkaczor
Copy link

@SrZorro I solved it like this:

const VmEventsEmitter: { new (): StrictEventEmitter<EventEmitter, IVmEvents> } = EventEmitter as any; // ugly AF any cast was required b/c i think i had old nodejs typings. That should not be important

export class VM extends VmEventsEmitter { 
    // ...
}

It's kinda ulgy but it works 😆

@bterlson
Copy link
Owner

@krzkaczor what version of node are you running? I can probably tweak the types so they work for that version.

As that's the only way I've found thus far to teach class methods about the stricter types, I'll add it to the docs!

@krzkaczor
Copy link

@bterlson typings are for 10.3.4

"@types/node@^10.3.4":
  version "10.3.4"

Thanks!

@bterlson
Copy link
Owner

I added an example of using this with classes (similar to @krzkaczor's solution). I'm not aware of a better way...

I'll leave this open so I remember to dig into the Node 10.3.4 typings.

@sywka
Copy link

sywka commented Oct 5, 2018

So, how should it look like if i have IEvents with generic types?
For example:

interface IEvents<Value> {
    onValueSended: Value;
}

class MyClass<Value> extends (EventEmitter as { new(): StrictEventEmitter<EventEmitter, IEvents<Value>> }) {
  ...
}

It throws error:
Error:(69, 45) TS2562: Base class expressions cannot reference class type parameters.

@krzkaczor
Copy link

@sywka
Copy link

sywka commented Oct 8, 2018

@krzkaczor I understand, but i need exactly generic for IEvents<Value> which is taken from MyClass<Value> and apparently this is impossible.

@esamattis
Copy link

Why not add a helper to do this?

Eg.

function createStrictEventEmitterClass<T>() {
    const TypedEmitter: {
        new (): StrictEventEmitter<EventEmitter, T>;
    } = EventEmitter as any;

    return TypedEmitter;
}

export class MyEventEmitter extends createStrictEventEmitterClass<MyEvents>() {

}

I can send a PR if you want this.

@svrooij
Copy link

svrooij commented Apr 15, 2020

@bterlson I would really like to see this added to your library.

Is someone working on this? @esamattis maybe? Or should I create a PR, and how do you want it structered in your Type only library?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants