npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@jpbberry/typed-emitter

v1.2.1

Published

Event emitter that creates types based off of an interface

Downloads

9,946

Readme

typed-emitter

Typed emitter providing fully typed methods of the base EventEmitter class

Installation

To install run npm i @jpbberry/typed-emitter

Usage

To use the typed-emitter, you can do so like

import { EventEmitter } from '@jpbberry/typed-emitter'

// a type
interface MyInterface {
  hello: boolean
}

// a class that you want to have typed emitters for
class MyClass extends EventEmitter<{ hello: MyInterface }> { // generic type has the map of events
  // this will then make all the methods have proper typings for the hello event and it's type
  run () {
    this.emit('hello', /* Will be typed as MyInterface */ { hello: true })

    // this will error for example
    this.emit('hello', { hello: 'world!' })
  }
}

const my = new MyClass()

my.on('hello', (data) => { // will be typed as MyInterface
  data.hello // typed as boolean
})

Adding multiple arguments

You can add multiple arguments by defining the property of the event to be an array, this will be spread as properties for the listener function etc.

For example

class MyClass extends EventEmitter<{ hello: [boolean, string] }> {
  run () {
    this.emit('hello', true, 'world!') // now the passed data will boolean, string
  }
}

const my = new MyClass()
my.on('hello', (one, two) => {
  one // boolean
  two // string
})

Defining an array as something passed to the event just has to be a nested array like { hello: [string[]] }

Decorators

As this simply amazing new TypeScript feature begins to gain traction, this library now has support for decorators

Our decorators are @Event and @Once

You use these by simply defining them in an extending EventEmitter class and passing your event name to them like @Event('message')

Here's an example

import { EventEmitter, Event, Once } from '@jpbberry/typed-emitter'

class MyClass extends EventEmitter<{ MESSAGE: string }> {
  // You can now simply just use the event decorator above any method you want ran on that event
  @Event('MESSAGE') // Listening to the event MESSAGE
  receivedMessage (message: string) { // the name of the method does NOT matter at all
    console.log(message) // logs the paramater!
  }
}

const my = new MyClass()
my.emit('MESSAGE', 'Hello world!') // logs "Hello world!"

Note you must enable experimentalDecorators in your tsconfig for these to work

ExtendedEmitter

This library also comes with an ExtendedEmitter for when a developer has made an emitter unavailable to you to extend / overwrite.

It allows you to use the decorators and all the features of the typed emitter while not having full control of the origin emitter

For example

import { ExtendedEmitter } from '@jpbberry/typed-emitter'

class MyOverrides extends ExtendedEmitter {
  @Event('message') // same concept as before!
  static onMessage (message: Message) { // make sure all of your methods are static, we aren't instantiating anything
    message.channel.send('Hello world!')
  }
}

// Now we just instantiate with the previous emitter
const client = new Client() // this uses the default emitter
MyOverrides.add(client) // this adds all of the events that were previously defined via the decorators

Instiated ExtendedEmitter

Especially useful when passing for example a manager to your event emitter, since you can't do this too well in static classes

A real usecase:

import { ExtendedEmitter } from '@jpbberry/typed-emitter'

class MyOverrides extends ExtendedEmitter {
  // since it's instantiated you can pass whatever you want to the constructor and use it elsewhere
  constructor (private client: Client) {
    super()
  }

  @Event('message')
  onMessage(msg: Message) { // make sure NOT to make this method static since you're instantiating
    if (msg.content === 'hello') {
      client.doSomething('hi!') // you'll have access to this client now
    }
  }
}

const client = new Client()

const overrides = new MyOverrides(client) // pass your options!
overrides.add(client) // add the new overrides

You can also use the applyToEmitter function if you want to use your own emitting options.