From 48555cb8ebb151c1c336849eef638b5d31783b0a Mon Sep 17 00:00:00 2001 From: Suneet Tipirneni <77477100+suneettipirneni@users.noreply.github.com> Date: Tue, 23 Nov 2021 04:23:14 -0500 Subject: [PATCH] types: make event emitters use mapped event types (#7019) --- typings/index.d.ts | 70 +++++++++++++++++++++++++++++++--------------- typings/tests.ts | 31 ++++++++++++++++++++ 2 files changed, 79 insertions(+), 22 deletions(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index 925e3f72a..7e68fd073 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -609,6 +609,12 @@ export class ClientVoiceManager { export { Collection } from '@discordjs/collection'; +export interface CollectorEventTypes { + collect: [V, ...F]; + dispose: [V, ...F]; + end: [collected: Collection, reason: string]; +} + export abstract class Collector extends EventEmitter { protected constructor(client: Client, options?: CollectorOptions<[V, ...F]>); private _timeout: NodeJS.Timeout | null; @@ -633,11 +639,15 @@ export abstract class Collector extends EventEmi public abstract collect(...args: unknown[]): K | null | Promise; public abstract dispose(...args: unknown[]): K | null; - public on(event: 'collect' | 'dispose', listener: (...args: [V, ...F]) => Awaitable): this; - public on(event: 'end', listener: (collected: Collection, reason: string) => Awaitable): this; + public on>( + event: EventKey, + listener: (...args: CollectorEventTypes[EventKey]) => Awaitable, + ): this; - public once(event: 'collect' | 'dispose', listener: (...args: [V, ...F]) => Awaitable): this; - public once(event: 'end', listener: (collected: Collection, reason: string) => Awaitable): this; + public once>( + event: EventKey, + listener: (...args: CollectorEventTypes[EventKey]) => Awaitable, + ): this; } export interface ApplicationCommandInteractionOptionResolver @@ -1829,6 +1839,16 @@ export class SelectMenuInteraction extends public inRawGuild(): this is SelectMenuInteraction<'raw'>; } +export interface ShardEventTypes { + spawn: [child: ChildProcess]; + death: [child: ChildProcess]; + disconnect: []; + ready: []; + reconnection: []; + error: [error: Error]; + message: [message: any]; +} + export class Shard extends EventEmitter { private constructor(manager: ShardingManager, id: number); private _evals: Map>; @@ -1853,17 +1873,15 @@ export class Shard extends EventEmitter { public send(message: unknown): Promise; public spawn(timeout?: number): Promise; - public on(event: 'spawn' | 'death', listener: (child: ChildProcess) => Awaitable): this; - public on(event: 'disconnect' | 'ready' | 'reconnecting', listener: () => Awaitable): this; - public on(event: 'error', listener: (error: Error) => Awaitable): this; - public on(event: 'message', listener: (message: any) => Awaitable): this; - public on(event: string, listener: (...args: any[]) => Awaitable): this; + public on( + event: K, + listener: (...args: ShardEventTypes[K]) => Awaitable, + ): this; - public once(event: 'spawn' | 'death', listener: (child: ChildProcess) => Awaitable): this; - public once(event: 'disconnect' | 'ready' | 'reconnecting', listener: () => Awaitable): this; - public once(event: 'error', listener: (error: Error) => Awaitable): this; - public once(event: 'message', listener: (message: any) => Awaitable): this; - public once(event: string, listener: (...args: any[]) => Awaitable): this; + public once( + event: K, + listener: (...args: ShardEventTypes[K]) => Awaitable, + ): this; } export class ShardClientUtil { @@ -2352,6 +2370,14 @@ export class WebSocketManager extends EventEmitter { private triggerClientReady(): void; } +export interface WebSocketShardEvents { + ready: []; + resumed: []; + invalidSession: []; + close: [event: CloseEvent]; + allReady: [unavailableGuilds?: Set]; +} + export class WebSocketShard extends EventEmitter { private constructor(manager: WebSocketManager, id: number); private sequence: number; @@ -2394,15 +2420,15 @@ export class WebSocketShard extends EventEmitter { public send(data: unknown, important?: boolean): void; - public on(event: 'ready' | 'resumed' | 'invalidSession', listener: () => Awaitable): this; - public on(event: 'close', listener: (event: CloseEvent) => Awaitable): this; - public on(event: 'allReady', listener: (unavailableGuilds?: Set) => Awaitable): this; - public on(event: string, listener: (...args: any[]) => Awaitable): this; + public on( + event: K, + listener: (...args: WebSocketShardEvents[K]) => Awaitable, + ): this; - public once(event: 'ready' | 'resumed' | 'invalidSession', listener: () => Awaitable): this; - public once(event: 'close', listener: (event: CloseEvent) => Awaitable): this; - public once(event: 'allReady', listener: (unavailableGuilds?: Set) => Awaitable): this; - public once(event: string, listener: (...args: any[]) => Awaitable): this; + public once( + event: K, + listener: (...args: WebSocketShardEvents[K]) => Awaitable, + ): this; } export class Widget extends Base { diff --git a/typings/tests.ts b/typings/tests.ts index 0269c3770..05c471cef 100644 --- a/typings/tests.ts +++ b/typings/tests.ts @@ -1,3 +1,4 @@ +import type { ChildProcess } from 'child_process'; import type { APIGuildMember, APIInteractionGuildMember, @@ -26,6 +27,7 @@ import { Client, ClientApplication, ClientUser, + CloseEvent, Collection, CommandInteraction, CommandInteractionOption, @@ -81,6 +83,8 @@ import { Shard, ApplicationCommandAutocompleteOption, ApplicationCommandNumericOptionData, + WebSocketShard, + Collector, } from '.'; import type { ApplicationCommandOptionTypes } from './enums'; @@ -1124,4 +1128,31 @@ client.on('interactionCreate', async interaction => { declare const shard: Shard; +shard.on('death', process => { + assertType(process); +}); + +declare const webSocketShard: WebSocketShard; + +webSocketShard.on('close', event => { + assertType(event); +}); + +declare const collector: Collector; + +collector.on('collect', (collected, ...other) => { + assertType(collected); + assertType(other); +}); + +collector.on('dispose', (vals, ...other) => { + assertType(vals); + assertType(other); +}); + +collector.on('end', (collection, reason) => { + assertType>(collection); + assertType(reason); +}); + assertType>(shard.eval(c => c.readyTimestamp));