{"id":22489222,"url":"https://github.com/Morglod/tseep","last_synced_at":"2025-08-02T21:32:18.429Z","repository":{"id":44067084,"uuid":"211566541","full_name":"Morglod/tseep","owner":"Morglod","description":"Fastest event emitter in the world for js (and only 381 bytes in build)","archived":false,"fork":false,"pushed_at":"2024-11-12T19:37:57.000Z","size":312,"stargazers_count":203,"open_issues_count":2,"forks_count":5,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-06-27T13:44:16.149Z","etag":null,"topics":["emitter","event-emitter","event-listener","eventbus","eventemitter","eventemitter3","eventlistener","events","fast","fastest","javascript","optimization","typescript"],"latest_commit_sha":null,"homepage":"https://github.com/Morglod/tseep/blob/master/benchmarks/README.md","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Morglod.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-28T21:59:44.000Z","updated_at":"2025-06-24T00:00:33.000Z","dependencies_parsed_at":"2024-06-18T22:54:54.827Z","dependency_job_id":"a7435160-42af-4ac1-98f9-958e229f9051","html_url":"https://github.com/Morglod/tseep","commit_stats":{"total_commits":31,"total_committers":2,"mean_commits":15.5,"dds":"0.032258064516129004","last_synced_commit":"552b31066508b4cc38ffe9b45c1871a527e02b23"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/Morglod/tseep","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Morglod%2Ftseep","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Morglod%2Ftseep/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Morglod%2Ftseep/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Morglod%2Ftseep/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Morglod","download_url":"https://codeload.github.com/Morglod/tseep/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Morglod%2Ftseep/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267474994,"owners_count":24093336,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-28T02:00:09.689Z","response_time":68,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["emitter","event-emitter","event-listener","eventbus","eventemitter","eventemitter3","eventlistener","events","fast","fastest","javascript","optimization","typescript"],"created_at":"2024-12-06T17:19:27.245Z","updated_at":"2025-08-02T21:32:17.991Z","avatar_url":"https://github.com/Morglod.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"[![NPM Version](https://badge.fury.io/js/tseep.svg?style=flat)](https://www.npmjs.com/package/tseep)\n[![GitHub stars](https://img.shields.io/github/stars/Morglod/tseep.svg?style=social\u0026label=Star)](https://GitHub.com/Morglod/tseep/)\n\n# tseep\n\nBecause there are N fastest event emitters. And we are fastest (November 2024) 😏.\n\nUp to **x12** faster than `eventemitter3` in terms of \"classic api event emitters\" (currently fastest for not classic too).\n\n---\n\n-   Fully typed args of `emit` method based on events map\n-   Fully implements `NodeJS.EventEmitter` type \u0026 standart, provides interface\n-   Worlds fastest pure-js `EventEmitter`\n-   Fully tested with eventemitter3 tests\n-   No external deps\n-   Only 381 bytes size in real app (brotlied)\n-   No eval implemented\n\n[how it works](./docs/how_it_works_en.md)\n\n## Benchmarks\n\nemit-multiple-listeners:\n```\ntseep               89,030,882 ops/sec\ntseep no-eval       15,235,353 ops/sec\nemitix              6,201,874 ops/sec\nfastemitter         5,981,406 ops/sec\nEventEmitter3       5,698,255 ops/sec\ntsee                5,163,550 ops/sec\nEventEmitter2       4,588,433 ops/sec\nEventEmitter1       4,437,743 ops/sec\nmitt                3,587,734 ops/sec\nevent-emitter       3,508,490 ops/sec\ncontra/emitter      2,183,943 ops/sec\n\nFastest is [ 'tseep' ]\n```\n\n[benchmarks](./benchmarks/README.md)\n\nMake an issue to include yours event emitter, lets find the fastest!\n\n## Install \u0026 use\n\n```\nnpm i tseep\n```\n\nSimple usage:\n\n```ts\nimport { EventEmitter } from \"tseep\";\n\nconst events = new EventEmitter\u003c{\n    foo: (a: number, b: string) =\u003e void;\n}\u003e();\n\n// foo's arguments is fully type checked\nevents.emit(\"foo\", 123, \"hello world\");\n```\n\n### Use no-eval version\n\nThere is no user code evaluated so its complete safe to use with-eval version.  \nBut in some cases (eg chrome's extensions), you just cant use it.  \nFor this cases there is no-eval version:\n\n```ts\nimport { EventEmitter } from \"tseep/lib/ee-safe\"; // no-eval version\nimport { EventEmitter } from \"tseep/lib/fallback\"; // or with autofallback\n\n// same api\n```\n\n\"tseep/lib/fallback\" may bundle both versions which may result in bigger app bundle size.  \nFun fact: brotlied bundled fallback version is less in size than just ee\n\n## Known issues\n\n#### __proto__ event name\n\n!! **`__proto__`** event name is restricted (type guard exists) !!\n\n#### context binding\n\nBy default listeners are not bound to EventEmitter, so you may get some problems around inheritance.  \nFirst of all, better use incapsulation. Its faster, safer, clear.  \nOther variant is to use addListenerBound/removeListenerBound.  \nIts 2-3x slower for add/remove operation but than you will have proper 'this' context inside listener.\n\n#### args length\n\ntseep tries to evade spread operator and pass arguments directly.  \nIt will always pass at least 5 arguments, filling non existing args as undefined.  \nSo if you use spread operator inside listener for arguments, you may have more args than you passed.  \nIt's a tradeoff for optimization.\n\nBetter use 5 or less arguments for listener, because js engine will optimize it and pass directly through registers.  \n(actually 6 arguments, but 1 argument is used as event name)\n\n## Api\n\n`EventEmitter\u003cT\u003e` where `T` extends `{ [eventName]: Call signature }`.\n\n`EventEmitter.emit`'s args is fully typed based on events map.\n\n```ts\n// Listener = (...args: any[]) =\u003e Promise\u003cany\u003e|void\n// EventMap extends { [event in (string|symbol)]: Listener }\n\nclass EventEmitter\u003cEventMap\u003e {\n    readonly maxListeners: number;\n    readonly _eventsCount: number;\n\n    emit(event: EventKey, ...args: ArgsN\u003cEventMap[EventKey]\u003e): boolean;\n    on(event: EventKey, listener: EventMap[EventKey]): this;\n    once(event: EventKey, listener: EventMap[EventKey]): this;\n    addListener(event: EventKey, listener: EventMap[EventKey], argsNum?: ArgsNum\u003cEventMap[EventKey]\u003e): this;\n    removeListener(event: EventKey, listener: EventMap[EventKey]): this;\n    hasListeners(event: EventKey): boolean;\n    prependListener(event: EventKey, listener: EventMap[EventKey]): this;\n    prependOnceListener(event: EventKey, listener: EventMap[EventKey]): this;\n    off(event: EventKey, listener: EventMap[EventKey]): this;\n    removeAllListeners(event?: EventKey): this;\n    setMaxListeners(n: number): this;\n    getMaxListeners(): number;\n    listeners(event: EventKey): EventMap[EventKey][];\n    rawListeners(event: EventKey): EventMap[EventKey][];\n    eventNames(): Array\u003cstring | symbol\u003e;\n    listenerCount(type: EventKey): number;\n\n    // special methods that are a bit slower than addListener/removeListener\n    // but they binds listeners to current EventEmitter or custom object\n    addListenerBound(event: EventKey, listener: EventMap[EventKey], bindTo?: any = this, argsNum?: ArgsNum\u003cEventMap[EventKey]\u003e): this;\n    removeListenerBound(event: EventKey, listener: EventMap[EventKey]): this;\n}\n```\n\n## Support this project\n\n[Boosty](https://boosty.to/morglod)\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMorglod%2Ftseep","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FMorglod%2Ftseep","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMorglod%2Ftseep/lists"}