diff --git a/eventemitter2.d.ts b/eventemitter2.d.ts
index 230825bc353849ffbc46a886099558bed9d42113..19405bde859cf454333ed08d0a2a7543291e9258 100644
--- a/eventemitter2.d.ts
+++ b/eventemitter2.d.ts
@@ -1,27 +1,24 @@
-export type event = (symbol|string);
-export type eventNS = string|event[];
-
 export interface ConstructorOptions {
     /**
      * @default false
      * @description set this to `true` to use wildcards.
      */
-    wildcard?: boolean,
+    wildcard?: boolean
     /**
      * @default '.'
      * @description the delimiter used to segment namespaces.
      */
-    delimiter?: string,
+    delimiter?: string
     /**
      * @default false
      * @description set this to `true` if you want to emit the newListener events.
      */
-    newListener?: boolean,
+    newListener?: boolean
     /**
      * @default false
      * @description set this to `true` if you want to emit the removeListener events.
      */
-    removeListener?: boolean,
+    removeListener?: boolean
     /**
      * @default 10
      * @description the maximum amount of listeners that can be assigned to an event.
@@ -38,39 +35,61 @@ export interface ConstructorOptions {
      */
     ignoreErrors?: boolean
 }
-export interface ListenerFn {
-    (...values: any[]): void;
-}
-export interface EventAndListener {
-    (event: string | string[], ...values: any[]): void;
+
+export type event = symbol | string
+export type eventNS = string | event[]
+
+export type EventMap = Record<event, (...values: any[]) => void>
+
+export type ListenerFn<
+    EventName extends keyof Events = event,
+    Events extends EventMap = EventMap
+> = Events[EventName]
+
+export interface EventAndListener<
+    EventName extends keyof Events = event,
+    Events extends EventMap = EventMap
+> {
+    (
+        event: EventName,
+        ...values: ListenerFunctionParameters<EventName, Events>
+    ): void
 }
 
-export interface WaitForFilter { (...values: any[]): boolean }
+export interface WaitForFilter<
+    EventName extends keyof Events = event,
+    Events extends EventMap = EventMap
+> {
+    (...values: ListenerFunctionParameters<EventName, Events>): boolean
+}
 
-export interface WaitForOptions {
+export interface WaitForOptions<
+    EventName extends keyof Events = event,
+    Events extends EventMap = EventMap
+> {
     /**
      * @default 0
      */
-    timeout: number,
+    timeout: number
     /**
      * @default null
      */
-    filter: WaitForFilter,
+    filter: WaitForFilter<EventName, Events>
     /**
      * @default false
      */
-    handleError: boolean,
+    handleError: boolean
     /**
      * @default Promise
      */
-    Promise: Function,
+    Promise: () => void
     /**
      * @default false
      */
     overload: boolean
 }
 
-export interface CancelablePromise<T> extends Promise<T>{
+export interface CancelablePromise<T> extends Promise<T> {
     cancel(reason: string): undefined
 }
 
@@ -78,79 +97,236 @@ export interface OnceOptions {
     /**
      * @default 0
      */
-    timeout: number,
+    timeout: number
     /**
      * @default Promise
      */
-    Promise: Function,
+    Promise: () => void
     /**
      * @default false
      */
     overload: boolean
 }
 
-export interface ListenToOptions {
-    on?: { (event: event | eventNS, handler: ListenerFn): void },
-    off?: { (event: event | eventNS, handler: ListenerFn): void },
-    reducers: Function | Object
+export interface ListenToOptions<
+    EventName extends keyof Events = event,
+    Events extends EventMap = EventMap
+> {
+    on?: {
+        (event: EventName | eventNS, handler: ListenerFn<EventName, Events>): void
+    }
+    off?: {
+        (event: EventName | eventNS, handler: ListenerFn<EventName, Events>): void
+    }
+    reducers: () => void | Record<string | number | symbol, unknown>
 }
 
-export interface GeneralEventEmitter{
-    addEventListener(event: event, handler: ListenerFn): this,
-    removeEventListener(event: event, handler: ListenerFn): this,
-    addListener?(event: event, handler: ListenerFn): this,
-    removeListener?(event: event, handler: ListenerFn): this,
-    on?(event: event, handler: ListenerFn): this,
-    off?(event: event, handler: ListenerFn): this
+export interface GeneralEventEmitter<
+    EventName extends keyof Events = event,
+    Events extends EventMap = EventMap
+> {
+    addEventListener(
+        event: EventName,
+        handler: ListenerFn<EventName, Events>
+    ): this
+
+    removeEventListener(
+        event: EventName,
+        handler: ListenerFn<EventName, Events>
+    ): this
+
+    addListener?(event: EventName, handler: ListenerFn<EventName, Events>): this
+
+    removeListener?(
+        event: EventName,
+        handler: ListenerFn<EventName, Events>
+    ): this
+
+    on?(event: EventName, handler: ListenerFn<EventName, Events>): this
+
+    off?(event: EventName, handler: ListenerFn<EventName, Events>): this
 }
 
 export interface OnOptions {
-    async?: boolean,
-    promisify?: boolean,
-    nextTick?: boolean,
+    async?: boolean
+    promisify?: boolean
+    nextTick?: boolean
     objectify?: boolean
 }
 
-export interface Listener {
-    emitter: EventEmitter2;
-    event: event|eventNS;
-    listener: ListenerFn;
-    off(): this;
+export interface Listener<
+    EventName extends keyof Events = event,
+    Events extends EventMap = EventMap
+> {
+    emitter: EventEmitter2<Events>
+    event: EventName | eventNS
+    listener: ListenerFn<EventName, Events>
+
+    off(): this
 }
 
-export declare class EventEmitter2 {
+export type ListenerFunctionParameters<
+    EventName extends keyof Events = event,
+    Events extends EventMap = EventMap
+> = Parameters<Events[EventName]>
+
+export class EventEmitter2<Events extends EventMap = EventMap> {
     constructor(options?: ConstructorOptions)
-    emit(event: event | eventNS, ...values: any[]): boolean;
-    emitAsync(event: event | eventNS, ...values: any[]): Promise<any[]>;
-    addListener(event: event | eventNS, listener: ListenerFn): this|Listener;
-    on(event: event | eventNS, listener: ListenerFn, options?: boolean|OnOptions): this|Listener;
-    prependListener(event: event | eventNS, listener: ListenerFn, options?: boolean|OnOptions): this|Listener;
-    once(event: event | eventNS, listener: ListenerFn, options?: true|OnOptions): this|Listener;
-    prependOnceListener(event: event | eventNS, listener: ListenerFn, options?: boolean|OnOptions): this|Listener;
-    many(event: event | eventNS, timesToListen: number, listener: ListenerFn, options?: boolean|OnOptions): this|Listener;
-    prependMany(event: event | eventNS, timesToListen: number, listener: ListenerFn, options?: boolean|OnOptions): this|Listener;
-    onAny(listener: EventAndListener): this;
-    prependAny(listener: EventAndListener): this;
-    offAny(listener: ListenerFn): this;
-    removeListener(event: event | eventNS, listener: ListenerFn): this;
-    off(event: event | eventNS, listener: ListenerFn): this;
-    removeAllListeners(event?: event | eventNS): this;
-    setMaxListeners(n: number): void;
-    getMaxListeners(): number;
-    eventNames(nsAsArray?: boolean): (event|eventNS)[];
-    listenerCount(event?: event | eventNS): number
-    listeners(event?: event | eventNS): ListenerFn[]
-    listenersAny(): ListenerFn[]
-    waitFor(event: event | eventNS, timeout?: number): CancelablePromise<any[]>
-    waitFor(event: event | eventNS, filter?: WaitForFilter): CancelablePromise<any[]>
-    waitFor(event: event | eventNS, options?: WaitForOptions): CancelablePromise<any[]>
-    listenTo(target: GeneralEventEmitter, events: event | eventNS, options?: ListenToOptions): this;
-    listenTo(target: GeneralEventEmitter, events: event[], options?: ListenToOptions): this;
-    listenTo(target: GeneralEventEmitter, events: Object, options?: ListenToOptions): this;
-    stopListeningTo(target?: GeneralEventEmitter, event?: event | eventNS): Boolean;
-    hasListeners(event?: String): Boolean
-    static once(emitter: EventEmitter2, event: event | eventNS, options?: OnceOptions): CancelablePromise<any[]>;
-    static defaultMaxListeners: number;
+
+    emit<EventName extends keyof Events>(
+        event: EventName,
+        ...values: ListenerFunctionParameters<EventName, Events>
+    ): boolean
+
+    emit(event: eventNS, ...values: unknown[]): boolean
+
+    emitAsync<EventName extends keyof Events>(
+        event: EventName | eventNS,
+        ...values: ListenerFunctionParameters<EventName, Events>
+    ): Promise<ReturnType<ListenerFn<EventName, Events>>[]>
+
+    addListener<EventName extends keyof Events>(
+        event: EventName | eventNS,
+        listener: ListenerFn<EventName, Events>
+    ): this | Listener<EventName, Events>
+
+    on<EventName extends keyof Events>(
+        event: EventName,
+        listener: ListenerFn<EventName, Events>,
+        options?: boolean | OnOptions
+    ): this | Listener<EventName, Events>
+
+    on(
+        event: eventNS,
+        listener: () => void,
+        options?: boolean | OnOptions
+    ): this | Listener<string, Events>
+
+    prependListener<EventName extends keyof Events>(
+        event: EventName | eventNS,
+        listener: ListenerFn<EventName, Events>,
+        options?: boolean | OnOptions
+    ): this | Listener<EventName, Events>
+
+    once<EventName extends keyof Events>(
+        event: EventName | eventNS,
+        listener: ListenerFn<EventName, Events>,
+        options?: true | OnOptions
+    ): this | Listener<EventName, Events>
+
+    prependOnceListener<EventName extends keyof Events>(
+        event: EventName | eventNS,
+        listener: ListenerFn<EventName, Events>,
+        options?: boolean | OnOptions
+    ): this | Listener<EventName, Events>
+
+    many<EventName extends keyof Events>(
+        event: EventName | eventNS,
+        timesToListen: number,
+        listener: ListenerFn<EventName, Events>,
+        options?: boolean | OnOptions
+    ): this | Listener<EventName, Events>
+
+    prependMany<EventName extends keyof Events>(
+        event: EventName | eventNS,
+        timesToListen: number,
+        listener: ListenerFn<EventName, Events>,
+        options?: boolean | OnOptions
+    ): this | Listener<EventName, Events>
+
+    onAny<EventName extends keyof Events>(
+        listener: EventAndListener<EventName, Events>
+    ): this
+
+    prependAny<EventName extends keyof Events>(
+        listener: EventAndListener<EventName, Events>
+    ): this
+
+    offAny<EventName extends keyof Events>(
+        listener: ListenerFn<EventName, Events>
+    ): this
+
+    removeListener<EventName extends keyof Events>(
+        event: EventName | eventNS,
+        listener: ListenerFn<EventName, Events>
+    ): this
+
+    off<EventName extends keyof Events>(
+        event: EventName | eventNS,
+        listener: ListenerFn<EventName, Events>
+    ): this
+
+    removeAllListeners<EventName extends keyof Events>(
+        event?: EventName | eventNS
+    ): this
+
+    setMaxListeners(numberOfListeners: number): void
+
+    getMaxListeners(): number
+
+    eventNames<EventName extends keyof Events>(
+        nsAsArray?: boolean
+    ): (EventName | eventNS)[]
+
+    listenerCount<EventName extends keyof Events>(
+        event?: EventName | eventNS
+    ): number
+
+    listeners<EventName extends keyof Events>(
+        event?: EventName | eventNS
+    ): ListenerFn<EventName, Events>[]
+
+    listenersAny<EventName extends keyof Events>(): ListenerFn<
+        EventName,
+        Events
+    >[]
+
+    waitFor<EventName extends keyof Events>(
+        event: EventName | eventNS,
+        timeout?: number
+    ): CancelablePromise<ListenerFunctionParameters<EventName, Events>>
+    waitFor<EventName extends keyof Events>(
+        event: EventName | eventNS,
+        filter?: WaitForFilter<EventName, Events>
+    ): CancelablePromise<ListenerFunctionParameters<EventName, Events>>
+    waitFor<EventName extends keyof Events>(
+        event: EventName | eventNS,
+        options?: WaitForOptions<EventName, Events>
+    ): CancelablePromise<ListenerFunctionParameters<EventName, Events>>
+
+    listenTo<EventName extends keyof Events>(
+        target: GeneralEventEmitter<EventName, Events>,
+        events: EventName | eventNS,
+        options?: ListenToOptions<EventName, Events>
+    ): this
+    listenTo<EventName extends keyof Events>(
+        target: GeneralEventEmitter<EventName, Events>,
+        events: EventName[],
+        options?: ListenToOptions<EventName, Events>
+    ): this
+    listenTo<EventName extends keyof Events>(
+        target: GeneralEventEmitter<EventName, Events>,
+        events: Record<string | number | symbol, unknown>,
+        options?: ListenToOptions<EventName, Events>
+    ): this
+
+    stopListeningTo<EventName extends keyof Events>(
+        target?: GeneralEventEmitter<EventName, Events>,
+        event?: EventName | eventNS
+    ): boolean
+
+    hasListeners<EventName extends keyof Events>(event?: EventName): boolean
+
+    static once<
+        EventName extends keyof Events = event,
+        Events extends EventMap = EventMap
+    >(
+        emitter: EventEmitter2<Events>,
+        event: EventName | eventNS,
+        options?: OnceOptions
+    ): CancelablePromise<ListenerFunctionParameters<EventName, Events>>
+
+    static defaultMaxListeners: number
 }
 
 export default EventEmitter2;
\ No newline at end of file
