https://github.com/trananhtung/typemit
Tiny, fully type-safe event emitter with a wildcard listener and a promise-based waitFor. Zero dependencies.
https://github.com/trananhtung/typemit
abortsignal emitter event-emitter events mitt pubsub type-safe typescript waitfor zero-dependency
Last synced: 4 days ago
JSON representation
Tiny, fully type-safe event emitter with a wildcard listener and a promise-based waitFor. Zero dependencies.
- Host: GitHub
- URL: https://github.com/trananhtung/typemit
- Owner: trananhtung
- License: mit
- Created: 2026-06-21T11:13:38.000Z (8 days ago)
- Default Branch: main
- Last Pushed: 2026-06-22T15:00:33.000Z (7 days ago)
- Last Synced: 2026-06-22T15:05:08.574Z (7 days ago)
- Topics: abortsignal, emitter, event-emitter, events, mitt, pubsub, type-safe, typescript, waitfor, zero-dependency
- Language: TypeScript
- Size: 46.9 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# typemit
[](#contributors-)
> Tiny, **fully type-safe** event emitter — with a wildcard listener and a promise-based **`waitFor`**. **Zero dependencies**.
[](https://github.com/trananhtung/typemit/actions/workflows/ci.yml)
[](https://www.npmjs.com/package/@billdaddy/typemit)
[](https://bundlephobia.com/package/@billdaddy/typemit)
[](https://www.npmjs.com/package/@billdaddy/typemit)
[](./LICENSE)
Most event emitters take `(string, ...any[])` and hope for the best. `typemit`
takes an **event map**, so the event name is checked, the payload type is inferred,
and a typo or wrong payload is a compile error — not a 2 a.m. bug.
```ts
import { createEmitter } from "@billdaddy/typemit";
const bus = createEmitter<{
login: { id: string };
message: string;
ready: void;
}>();
bus.on("login", (user) => console.log(user.id)); // user: { id: string }
bus.emit("login", { id: "42" });
bus.emit("ready"); // void event — no payload
bus.emit("login", "oops"); // ❌ compile error
```
## Why typemit?
- **Type-safe end to end.** `on`/`once`/`emit`/`waitFor` are all checked against
your event map; `void` events take no payload.
- **`waitFor` as a promise.** Await the next event — with an optional `filter` and
an `AbortSignal` to bail out. Great for tests and request/response flows.
- **Wildcard listener.** `onAny((event, payload) => …)` for logging/debugging.
- **Tidy lifecycle.** `on`/`once`/`onAny` return an unsubscribe; `clear()` and
`listenerCount()` for housekeeping. Handlers may unsubscribe themselves mid-emit.
- **Zero dependencies**, ESM + CJS + types, ~1 kB.
## Install
```bash
npm install @billdaddy/typemit
# or: pnpm add @billdaddy/typemit / yarn add @billdaddy/typemit / bun add @billdaddy/typemit
```
## API
```ts
const bus = createEmitter();
```
### Subscribe / emit
```ts
const off = bus.on("message", (text) => …); // returns unsubscribe
bus.once("ready", () => …); // fires once
bus.off("message", handler);
bus.emit("message", "hello");
off();
```
### `waitFor(event, { signal?, filter? }) → Promise`
```ts
const user = await bus.waitFor("login");
const big = await bus.waitFor("message", { filter: (m) => m.length > 100 });
const ac = new AbortController();
const next = bus.waitFor("login", { signal: ac.signal }); // rejects if aborted
```
### Wildcard & housekeeping
```ts
const offAny = bus.onAny((event, payload) => log(event, payload));
bus.listenerCount("message"); // listeners for one event
bus.listenerCount(); // all listeners, incl. wildcard
bus.clear("message"); // remove one event's listeners
bus.clear(); // remove everything
```
## Pairs well with
- [`timefence`](https://www.npmjs.com/package/timefence) — race `waitFor` against a deadline.
## Contributors ✨
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind are welcome — code, docs, bug reports, ideas, reviews! See the [emoji key](https://allcontributors.org/docs/en/emoji-key) for how each contribution is recognized, and open a PR or issue to get involved.
Thanks goes to these wonderful people:
## License
[MIT](./LICENSE) © Tung Tran