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 🙏

© 2025 – Pkg Stats / Ryan Hefner

jaset

v1.1.0

Published

A simple, type-safe implementation of EventTarget with zero dependencies and select enhancements for a better developer experience.

Readme

jaset (just a strict event target) is a simple, type-safe implementation of EventTarget with zero dependencies and select enhancements for a better developer experience — including short-form method names, event muting, an optional wildcard event type and more.

Installation

npm i jaset

See Package exports for a list of all package exports.

Usage

You can use jaset just like you would use EventTarget with the addition of providing an event map.

import EventTarget, { type EventMap } from "jaset"

class MyEventTarget extends EventTarget<MyEventMap> {}

type MyEventMap = EventMap<{
	"my-event": MyEvent
}>

const myEventTarget = new MyEventTarget()

// ✅ "my-event" is a valid event type: No complaints.
myEventTarget.on("my-event", (event) => {
	// ✅ event is `MyEvent` and not just any `Event`.
})

// ⛔️ "foo" is not a valid event type: TypeScript error.
myEventTarget.on("foo", (event) => {
	// ...
})

Define custom events

jaset supports events that extend Event.

class MyEvent extends Event {
	constructor() {
		super("my-event")
	}
}

If you prefer to use CustomEvent, just use it directly in your event map.

type MyEventMap = EventMap<{
	"my-event": CustomEvent<number>
}>

Add event listeners

Documentation

myEventTarget.on("my-event", onMyEvent)
myEventTarget.addEventListener("my-event", onMyEvent)

function onMyEvent(event: MyEvent) {
	// ...
}

[!NOTE] Just like it is the case with EventTarget, an attempt to add the same event listener twice will be ignored without throwing an error.

Once

Once event listeners are listeners that are only invoked once and then removed.

Documentation

myEventTarget.once("my-event", onMyEvent)
myEventTarget.addEventListener("my-event", onMyEvent, { once: true })

Dispatch events

Documentation

myEventTarget.emit(new MyEvent())
myEventTarget.dispatchEvent(new MyEvent())

Remove event listeners

Documentation

myEventTarget.off("my-event", onMyEvent)
myEventTarget.removeEventListener("my-event", onMyEvent)

Remove all event listeners

You can remove all event listeners for a specific event type.

myEventTarget.clear("my-event")

Event listener map

A Map of event types to event listeners is available via eventListeners:

myEventTarget.eventListeners
// Map<keyof MyEventMap | "*", EventListener[]>

[!NOTE] This map only contains active event listeners. Event types are removed once their last event listener is removed. Wildcard event listeners, if present, are also included in this map with an event type of "*".

Mute events

You can mute all events of a certain type, allowing you to prevent all event listeners from invoking until you unmute.

// Mute. 🔇
myEventTarget.mute("my-event")

// Ignored. 🙈
myEventTarget.emit(new MyEvent())

// Unmute. 🔊
myEventTarget.unmute("my-event")

A Set of all muted event types is available via mutedEventTypes:

myEventTarget.mutedEventTypes
// Set<keyof MyEventMap>

Wildcard event type

With the optional wildcard event type ("*") you can reference all event types at once. This is supported by all jaset methods, except emit() and dispatchEvent().

myEventTarget.on("*", onAnyEvent)
myEventTarget.off("*", onAnyEvent)
myEventTarget.clear("*")
myEventTarget.mute("*")
myEventTarget.unmute("*")

function onAnyEvent(event: MyEvent | MyOtherEvent) {
	// Eyes on everyone. 👀
}

[!IMPORTANT] The wildcard event type is disallowed by default for cleaner IntelliSense suggestions. You can allow it by setting the generic type parameter AllowWildcardEventType to true.

import EventTarget from "jaset"

class MyEventTarget extends EventTarget<
	MyEventMap,
	/* AllowWildcardEventType */ true
> {}

Combine event maps

You can combine multiple event maps when extending the jaset event target.

import EventTarget, { type EventMap } from "jaset"

class MyEventTarget<
	MyEventMap extends EventMap<MyEventMap>,
> extends EventTarget<BaseEventMap & MyEventMap> {}

type BaseEventMap = EventMap<{
	"my-event": MyEvent
}>

class MyEventTargetExtension extends MyEventTarget<ExtensionEventMap> {}

type ExtensionEventMap = EventMap<{
	"my-other-event": MyOtherEvent
}>

const myEventTarget = new MyEventTargetExtension()

myEventTarget.on("my-event", () => {}) // ✅
myEventTarget.on("my-other-event", () => {}) // ✅
myEventTarget.on("foo", () => {}) // ⛔️

Combining event maps can be useful when designing an interface where clients should be able to extend the base event map you define.

You can prevent clients from being able to override entries from the base event map by utilizing Omit:

class MyEventTarget<
	MyEventMap extends Omit<EventMap<MyEventMap>, keyof BaseEventMap>,
> extends EventTarget<BaseEventMap & MyEventMap> {}

Package exports

The jaset package exports the following:

  • Event target class

    import EventTarget from "jaset"
    // or
    import { EventTarget } from "jaset"
  • Map of event types to events (type only)

    import type { EventMap } from "jaset"

    Used for defining custom event maps.

    type MyEventMap = EventMap<{
    	"my-event": MyEvent
    }>

    When the type parameter of EventMap is omitted, the event map becomes Record<string, Event>.