types: Ensure events possess Client<true> (#8612)

types: ensure events possess `Client<true>`

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
Jiralite
2022-09-11 19:36:24 +01:00
committed by GitHub
parent 1d4cdee321
commit a9f003ac9b
2 changed files with 541 additions and 390 deletions

View File

@@ -281,7 +281,7 @@ export class ActivityFlagsBitField extends BitField<ActivityFlagsString> {
} }
export abstract class AnonymousGuild extends BaseGuild { export abstract class AnonymousGuild extends BaseGuild {
protected constructor(client: Client, data: RawAnonymousGuildData, immediatePatch?: boolean); protected constructor(client: Client<true>, data: RawAnonymousGuildData, immediatePatch?: boolean);
public banner: string | null; public banner: string | null;
public description: string | null; public description: string | null;
public nsfwLevel: GuildNSFWLevel; public nsfwLevel: GuildNSFWLevel;
@@ -294,7 +294,7 @@ export abstract class AnonymousGuild extends BaseGuild {
} }
export abstract class Application extends Base { export abstract class Application extends Base {
protected constructor(client: Client, data: RawApplicationData); protected constructor(client: Client<true>, data: RawApplicationData);
public get createdAt(): Date; public get createdAt(): Date;
public get createdTimestamp(): number; public get createdTimestamp(): number;
public description: string | null; public description: string | null;
@@ -308,7 +308,7 @@ export abstract class Application extends Base {
} }
export class ApplicationCommand<PermissionsFetchType = {}> extends Base { export class ApplicationCommand<PermissionsFetchType = {}> extends Base {
private constructor(client: Client, data: RawApplicationCommandData, guild?: Guild, guildId?: Snowflake); private constructor(client: Client<true>, data: RawApplicationCommandData, guild?: Guild, guildId?: Snowflake);
public applicationId: Snowflake; public applicationId: Snowflake;
public get createdAt(): Date; public get createdAt(): Date;
public get createdTimestamp(): number; public get createdTimestamp(): number;
@@ -373,8 +373,8 @@ export class ApplicationFlagsBitField extends BitField<ApplicationFlagsString> {
} }
export abstract class Base { export abstract class Base {
public constructor(client: Client); public constructor(client: Client<true>);
public readonly client: Client; public readonly client: Client<true>;
public toJSON(...props: Record<string, boolean | string>[]): unknown; public toJSON(...props: Record<string, boolean | string>[]): unknown;
public valueOf(): string; public valueOf(): string;
} }
@@ -474,7 +474,7 @@ export class InteractionResponse<Cached extends boolean = boolean> {
} }
export abstract class BaseGuild extends Base { export abstract class BaseGuild extends Base {
protected constructor(client: Client, data: RawBaseGuildData); protected constructor(client: Client<true>, data: RawBaseGuildData);
public get createdAt(): Date; public get createdAt(): Date;
public get createdTimestamp(): number; public get createdTimestamp(): number;
public features: `${GuildFeature}`[]; public features: `${GuildFeature}`[];
@@ -490,7 +490,7 @@ export abstract class BaseGuild extends Base {
} }
export class BaseGuildEmoji extends Emoji { export class BaseGuildEmoji extends Emoji {
protected constructor(client: Client, data: RawGuildEmojiData, guild: Guild | GuildPreview); protected constructor(client: Client<true>, data: RawGuildEmojiData, guild: Guild | GuildPreview);
public available: boolean | null; public available: boolean | null;
public get createdAt(): Date; public get createdAt(): Date;
public get createdTimestamp(): number; public get createdTimestamp(): number;
@@ -501,7 +501,7 @@ export class BaseGuildEmoji extends Emoji {
} }
export class BaseGuildTextChannel extends TextBasedChannelMixin(GuildChannel, true) { export class BaseGuildTextChannel extends TextBasedChannelMixin(GuildChannel, true) {
protected constructor(guild: Guild, data?: RawGuildChannelData, client?: Client, immediatePatch?: boolean); protected constructor(guild: Guild, data?: RawGuildChannelData, client?: Client<true>, immediatePatch?: boolean);
public defaultAutoArchiveDuration?: ThreadAutoArchiveDuration; public defaultAutoArchiveDuration?: ThreadAutoArchiveDuration;
public rateLimitPerUser: number | null; public rateLimitPerUser: number | null;
public nsfw: boolean; public nsfw: boolean;
@@ -553,7 +553,7 @@ export class BitField<S extends string, N extends number | bigint = number> {
} }
export class ButtonInteraction<Cached extends CacheType = CacheType> extends MessageComponentInteraction<Cached> { export class ButtonInteraction<Cached extends CacheType = CacheType> extends MessageComponentInteraction<Cached> {
private constructor(client: Client, data: RawMessageButtonInteractionData); private constructor(client: Client<true>, data: RawMessageButtonInteractionData);
public componentType: ComponentType.Button; public componentType: ComponentType.Button;
public get component(): CacheTypeReducer< public get component(): CacheTypeReducer<
Cached, Cached,
@@ -725,7 +725,7 @@ export class CategoryChannel extends GuildChannel {
export type CategoryChannelResolvable = Snowflake | CategoryChannel; export type CategoryChannelResolvable = Snowflake | CategoryChannel;
export abstract class BaseChannel extends Base { export abstract class BaseChannel extends Base {
public constructor(client: Client, data?: RawChannelData, immediatePatch?: boolean); public constructor(client: Client<true>, data?: RawChannelData, immediatePatch?: boolean);
public get createdAt(): Date | null; public get createdAt(): Date | null;
public get createdTimestamp(): number | null; public get createdTimestamp(): number | null;
public id: Snowflake; public id: Snowflake;
@@ -805,7 +805,7 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
} }
export class ClientApplication extends Application { export class ClientApplication extends Application {
private constructor(client: Client, data: RawClientApplicationData); private constructor(client: Client<true>, data: RawClientApplicationData);
public botPublic: boolean | null; public botPublic: boolean | null;
public botRequireCodeGrant: boolean | null; public botRequireCodeGrant: boolean | null;
public commands: ApplicationCommandManager; public commands: ApplicationCommandManager;
@@ -821,7 +821,7 @@ export class ClientApplication extends Application {
} }
export class ClientPresence extends Presence { export class ClientPresence extends Presence {
private constructor(client: Client, data: RawPresenceData); private constructor(client: Client<true>, data: RawPresenceData);
private _parse(data: PresenceData): RawPresenceData; private _parse(data: PresenceData): RawPresenceData;
public set(presence: PresenceData): ClientPresence; public set(presence: PresenceData): ClientPresence;
@@ -866,7 +866,7 @@ export interface CollectorEventTypes<K, V, F extends unknown[] = []> {
} }
export abstract class Collector<K, V, F extends unknown[] = []> extends EventEmitter { export abstract class Collector<K, V, F extends unknown[] = []> extends EventEmitter {
protected constructor(client: Client, options?: CollectorOptions<[V, ...F]>); protected constructor(client: Client<true>, options?: CollectorOptions<[V, ...F]>);
private _timeout: NodeJS.Timeout | null; private _timeout: NodeJS.Timeout | null;
private _idletimeout: NodeJS.Timeout | null; private _idletimeout: NodeJS.Timeout | null;
private _endReason: string | null; private _endReason: string | null;
@@ -930,7 +930,11 @@ export class AutocompleteInteraction<Cached extends CacheType = CacheType> exten
} }
export class CommandInteractionOptionResolver<Cached extends CacheType = CacheType> { export class CommandInteractionOptionResolver<Cached extends CacheType = CacheType> {
private constructor(client: Client, options: CommandInteractionOption[], resolved: CommandInteractionResolvedData); private constructor(
client: Client<true>,
options: CommandInteractionOption[],
resolved: CommandInteractionResolvedData,
);
public readonly client: Client; public readonly client: Client;
public readonly data: readonly CommandInteractionOption<Cached>[]; public readonly data: readonly CommandInteractionOption<Cached>[];
public readonly resolved: Readonly<CommandInteractionResolvedData<Cached>> | null; public readonly resolved: Readonly<CommandInteractionResolvedData<Cached>> | null;
@@ -1035,7 +1039,7 @@ export class DMChannel extends TextBasedChannelMixin(BaseChannel, false, [
'setRateLimitPerUser', 'setRateLimitPerUser',
'setNSFW', 'setNSFW',
]) { ]) {
private constructor(client: Client, data?: RawDMChannelData); private constructor(client: Client<true>, data?: RawDMChannelData);
public recipientId: Snowflake; public recipientId: Snowflake;
public get recipient(): User | null; public get recipient(): User | null;
public type: ChannelType.DM; public type: ChannelType.DM;
@@ -1044,7 +1048,7 @@ export class DMChannel extends TextBasedChannelMixin(BaseChannel, false, [
} }
export class Emoji extends Base { export class Emoji extends Base {
protected constructor(client: Client, emoji: RawEmojiData); protected constructor(client: Client<true>, emoji: RawEmojiData);
public animated: boolean | null; public animated: boolean | null;
public get createdAt(): Date | null; public get createdAt(): Date | null;
public get createdTimestamp(): number | null; public get createdTimestamp(): number | null;
@@ -1057,7 +1061,7 @@ export class Emoji extends Base {
} }
export class Guild extends AnonymousGuild { export class Guild extends AnonymousGuild {
private constructor(client: Client, data: RawGuildData); private constructor(client: Client<true>, data: RawGuildData);
private _sortedRoles(): Collection<Snowflake, Role>; private _sortedRoles(): Collection<Snowflake, Role>;
private _sortedChannels(channel: NonThreadGuildBasedChannel): Collection<Snowflake, NonThreadGuildBasedChannel>; private _sortedChannels(channel: NonThreadGuildBasedChannel): Collection<Snowflake, NonThreadGuildBasedChannel>;
@@ -1203,7 +1207,7 @@ export class GuildAuditLogsEntry<
} }
export class GuildBan extends Base { export class GuildBan extends Base {
private constructor(client: Client, data: RawGuildBanData, guild: Guild); private constructor(client: Client<true>, data: RawGuildBanData, guild: Guild);
public guild: Guild; public guild: Guild;
public user: User; public user: User;
public get partial(): boolean; public get partial(): boolean;
@@ -1212,7 +1216,7 @@ export class GuildBan extends Base {
} }
export abstract class GuildChannel extends BaseChannel { export abstract class GuildChannel extends BaseChannel {
public constructor(guild: Guild, data?: RawGuildChannelData, client?: Client, immediatePatch?: boolean); public constructor(guild: Guild, data?: RawGuildChannelData, client?: Client<true>, immediatePatch?: boolean);
private memberPermissions(member: GuildMember, checkAdmin: boolean): Readonly<PermissionsBitField>; private memberPermissions(member: GuildMember, checkAdmin: boolean): Readonly<PermissionsBitField>;
private rolePermissions(role: Role, checkAdmin: boolean): Readonly<PermissionsBitField>; private rolePermissions(role: Role, checkAdmin: boolean): Readonly<PermissionsBitField>;
public get createdAt(): Date; public get createdAt(): Date;
@@ -1249,7 +1253,7 @@ export abstract class GuildChannel extends BaseChannel {
} }
export class GuildEmoji extends BaseGuildEmoji { export class GuildEmoji extends BaseGuildEmoji {
private constructor(client: Client, data: RawGuildEmojiData, guild: Guild); private constructor(client: Client<true>, data: RawGuildEmojiData, guild: Guild);
private _roles: Snowflake[]; private _roles: Snowflake[];
public get deletable(): boolean; public get deletable(): boolean;
@@ -1265,7 +1269,7 @@ export class GuildEmoji extends BaseGuildEmoji {
} }
export class GuildMember extends PartialTextBasedChannel(Base) { export class GuildMember extends PartialTextBasedChannel(Base) {
private constructor(client: Client, data: RawGuildMemberData, guild: Guild); private constructor(client: Client<true>, data: RawGuildMemberData, guild: Guild);
public avatar: string | null; public avatar: string | null;
public get bannable(): boolean; public get bannable(): boolean;
public get dmChannel(): DMChannel | null; public get dmChannel(): DMChannel | null;
@@ -1313,7 +1317,7 @@ export class GuildMember extends PartialTextBasedChannel(Base) {
} }
export class GuildPreview extends Base { export class GuildPreview extends Base {
private constructor(client: Client, data: RawGuildPreviewData); private constructor(client: Client<true>, data: RawGuildPreviewData);
public approximateMemberCount: number; public approximateMemberCount: number;
public approximatePresenceCount: number; public approximatePresenceCount: number;
public get createdAt(): Date; public get createdAt(): Date;
@@ -1336,7 +1340,7 @@ export class GuildPreview extends Base {
} }
export class GuildScheduledEvent<S extends GuildScheduledEventStatus = GuildScheduledEventStatus> extends Base { export class GuildScheduledEvent<S extends GuildScheduledEventStatus = GuildScheduledEventStatus> extends Base {
private constructor(client: Client, data: RawGuildScheduledEventData); private constructor(client: Client<true>, data: RawGuildScheduledEventData);
public id: Snowflake; public id: Snowflake;
public guildId: Snowflake; public guildId: Snowflake;
public channelId: Snowflake | null; public channelId: Snowflake | null;
@@ -1386,7 +1390,7 @@ export class GuildScheduledEvent<S extends GuildScheduledEventStatus = GuildSche
} }
export class GuildTemplate extends Base { export class GuildTemplate extends Base {
private constructor(client: Client, data: RawGuildTemplateData); private constructor(client: Client<true>, data: RawGuildTemplateData);
public createdTimestamp: number; public createdTimestamp: number;
public updatedTimestamp: number; public updatedTimestamp: number;
public get url(): string; public get url(): string;
@@ -1410,13 +1414,13 @@ export class GuildTemplate extends Base {
} }
export class GuildPreviewEmoji extends BaseGuildEmoji { export class GuildPreviewEmoji extends BaseGuildEmoji {
private constructor(client: Client, data: RawGuildEmojiData, guild: GuildPreview); private constructor(client: Client<true>, data: RawGuildEmojiData, guild: GuildPreview);
public guild: GuildPreview; public guild: GuildPreview;
public roles: Snowflake[]; public roles: Snowflake[];
} }
export class Integration extends Base { export class Integration extends Base {
private constructor(client: Client, data: RawIntegrationData, guild: Guild); private constructor(client: Client<true>, data: RawIntegrationData, guild: Guild);
public account: IntegrationAccount; public account: IntegrationAccount;
public application: IntegrationApplication | null; public application: IntegrationApplication | null;
public enabled: boolean | null; public enabled: boolean | null;
@@ -1440,7 +1444,7 @@ export class Integration extends Base {
} }
export class IntegrationApplication extends Application { export class IntegrationApplication extends Application {
private constructor(client: Client, data: RawIntegrationApplicationData); private constructor(client: Client<true>, data: RawIntegrationApplicationData);
public bot: User | null; public bot: User | null;
public termsOfServiceURL: string | null; public termsOfServiceURL: string | null;
public privacyPolicyURL: string | null; public privacyPolicyURL: string | null;
@@ -1486,7 +1490,7 @@ export type RepliableInteraction<Cached extends CacheType = CacheType> = Exclude
export class BaseInteraction<Cached extends CacheType = CacheType> extends Base { export class BaseInteraction<Cached extends CacheType = CacheType> extends Base {
// This a technique used to brand different cached types. Or else we'll get `never` errors on typeguard checks. // This a technique used to brand different cached types. Or else we'll get `never` errors on typeguard checks.
private readonly _cacheType: Cached; private readonly _cacheType: Cached;
protected constructor(client: Client, data: RawInteractionData); protected constructor(client: Client<true>, data: RawInteractionData);
public applicationId: Snowflake; public applicationId: Snowflake;
public get channel(): CacheTypeReducer< public get channel(): CacheTypeReducer<
Cached, Cached,
@@ -1531,7 +1535,7 @@ export class InteractionCollector<T extends CollectedInteraction> extends Collec
T, T,
[Collection<Snowflake, T>] [Collection<Snowflake, T>]
> { > {
public constructor(client: Client, options?: InteractionCollectorOptions<T>); public constructor(client: Client<true>, options?: InteractionCollectorOptions<T>);
private _handleMessageDeletion(message: Message): void; private _handleMessageDeletion(message: Message): void;
private _handleChannelDeletion(channel: NonThreadGuildBasedChannel): void; private _handleChannelDeletion(channel: NonThreadGuildBasedChannel): void;
private _handleGuildDeletion(guild: Guild): void; private _handleGuildDeletion(guild: Guild): void;
@@ -1559,7 +1563,7 @@ export class InteractionCollector<T extends CollectedInteraction> extends Collec
} }
export class InteractionWebhook extends PartialWebhookMixin() { export class InteractionWebhook extends PartialWebhookMixin() {
public constructor(client: Client, id: Snowflake, token: string); public constructor(client: Client<true>, id: Snowflake, token: string);
public token: string; public token: string;
public send(options: string | MessagePayload | InteractionReplyOptions): Promise<Message>; public send(options: string | MessagePayload | InteractionReplyOptions): Promise<Message>;
public editMessage( public editMessage(
@@ -1570,7 +1574,7 @@ export class InteractionWebhook extends PartialWebhookMixin() {
} }
export class Invite extends Base { export class Invite extends Base {
private constructor(client: Client, data: RawInviteData); private constructor(client: Client<true>, data: RawInviteData);
public channel: NonThreadGuildBasedChannel | PartialGroupDMChannel | null; public channel: NonThreadGuildBasedChannel | PartialGroupDMChannel | null;
public channelId: Snowflake | null; public channelId: Snowflake | null;
public code: string; public code: string;
@@ -1603,7 +1607,7 @@ export class Invite extends Base {
/** @deprecated */ /** @deprecated */
export class InviteStageInstance extends Base { export class InviteStageInstance extends Base {
private constructor(client: Client, data: RawInviteStageInstance, channelId: Snowflake, guildId: Snowflake); private constructor(client: Client<true>, data: RawInviteStageInstance, channelId: Snowflake, guildId: Snowflake);
public channelId: Snowflake; public channelId: Snowflake;
public guildId: Snowflake; public guildId: Snowflake;
public members: Collection<Snowflake, GuildMember>; public members: Collection<Snowflake, GuildMember>;
@@ -1615,7 +1619,7 @@ export class InviteStageInstance extends Base {
} }
export class InviteGuild extends AnonymousGuild { export class InviteGuild extends AnonymousGuild {
private constructor(client: Client, data: RawInviteGuildData); private constructor(client: Client<true>, data: RawInviteGuildData);
public welcomeScreen: WelcomeScreen | null; public welcomeScreen: WelcomeScreen | null;
} }
@@ -1658,7 +1662,7 @@ export interface MappedInteractionTypes<Cached extends boolean = boolean> {
export class Message<InGuild extends boolean = boolean> extends Base { export class Message<InGuild extends boolean = boolean> extends Base {
private readonly _cacheType: InGuild; private readonly _cacheType: InGuild;
private constructor(client: Client, data: RawMessageData); private constructor(client: Client<true>, data: RawMessageData);
private _patch(data: RawPartialMessageData | RawMessageData): void; private _patch(data: RawPartialMessageData | RawMessageData): void;
public activity: MessageActivity | null; public activity: MessageActivity | null;
@@ -1773,7 +1777,7 @@ export class MessageCollector extends Collector<Snowflake, Message, [Collection<
} }
export class MessageComponentInteraction<Cached extends CacheType = CacheType> extends BaseInteraction<Cached> { export class MessageComponentInteraction<Cached extends CacheType = CacheType> extends BaseInteraction<Cached> {
protected constructor(client: Client, data: RawMessageComponentInteractionData); protected constructor(client: Client<true>, data: RawMessageComponentInteractionData);
public type: InteractionType.MessageComponent; public type: InteractionType.MessageComponent;
public get component(): CacheTypeReducer< public get component(): CacheTypeReducer<
Cached, Cached,
@@ -1910,10 +1914,10 @@ export class MessagePayload {
} }
export class MessageReaction { export class MessageReaction {
private constructor(client: Client, data: RawMessageReactionData, message: Message); private constructor(client: Client<true>, data: RawMessageReactionData, message: Message);
private _emoji: GuildEmoji | ReactionEmoji; private _emoji: GuildEmoji | ReactionEmoji;
public readonly client: Client; public readonly client: Client<true>;
public count: number; public count: number;
public get emoji(): GuildEmoji | ReactionEmoji; public get emoji(): GuildEmoji | ReactionEmoji;
public me: boolean; public me: boolean;
@@ -1975,7 +1979,7 @@ export interface ModalMessageModalSubmitInteraction<Cached extends CacheType = C
} }
export class ModalSubmitInteraction<Cached extends CacheType = CacheType> extends BaseInteraction<Cached> { export class ModalSubmitInteraction<Cached extends CacheType = CacheType> extends BaseInteraction<Cached> {
private constructor(client: Client, data: APIModalSubmitInteraction); private constructor(client: Client<true>, data: APIModalSubmitInteraction);
public type: InteractionType.ModalSubmit; public type: InteractionType.ModalSubmit;
public readonly customId: string; public readonly customId: string;
public readonly components: ActionRowModalData[]; public readonly components: ActionRowModalData[];
@@ -2014,13 +2018,13 @@ export class NewsChannel extends BaseGuildTextChannel {
} }
export class OAuth2Guild extends BaseGuild { export class OAuth2Guild extends BaseGuild {
private constructor(client: Client, data: RawOAuth2GuildData); private constructor(client: Client<true>, data: RawOAuth2GuildData);
public owner: boolean; public owner: boolean;
public permissions: Readonly<PermissionsBitField>; public permissions: Readonly<PermissionsBitField>;
} }
export class PartialGroupDMChannel extends BaseChannel { export class PartialGroupDMChannel extends BaseChannel {
private constructor(client: Client, data: RawPartialGroupDMChannelData); private constructor(client: Client<true>, data: RawPartialGroupDMChannelData);
public type: ChannelType.GroupDM; public type: ChannelType.GroupDM;
public name: string | null; public name: string | null;
public icon: string | null; public icon: string | null;
@@ -2030,7 +2034,7 @@ export class PartialGroupDMChannel extends BaseChannel {
} }
export class PermissionOverwrites extends Base { export class PermissionOverwrites extends Base {
private constructor(client: Client, data: RawPermissionOverwriteData, channel: NonThreadGuildBasedChannel); private constructor(client: Client<true>, data: RawPermissionOverwriteData, channel: NonThreadGuildBasedChannel);
public allow: Readonly<PermissionsBitField>; public allow: Readonly<PermissionsBitField>;
public readonly channel: NonThreadGuildBasedChannel; public readonly channel: NonThreadGuildBasedChannel;
public deny: Readonly<PermissionsBitField>; public deny: Readonly<PermissionsBitField>;
@@ -2063,7 +2067,7 @@ export class PermissionsBitField extends BitField<PermissionsString, bigint> {
} }
export class Presence extends Base { export class Presence extends Base {
protected constructor(client: Client, data?: RawPresenceData); protected constructor(client: Client<true>, data?: RawPresenceData);
public activities: Activity[]; public activities: Activity[];
public clientStatus: ClientPresenceStatusData | null; public clientStatus: ClientPresenceStatusData | null;
public guild: Guild | null; public guild: Guild | null;
@@ -2126,7 +2130,7 @@ export class RichPresenceAssets {
} }
export class Role extends Base { export class Role extends Base {
private constructor(client: Client, data: RawRoleData, guild: Guild); private constructor(client: Client<true>, data: RawRoleData, guild: Guild);
public color: number; public color: number;
public get createdAt(): Date; public get createdAt(): Date;
public get createdTimestamp(): number; public get createdTimestamp(): number;
@@ -2167,7 +2171,7 @@ export class Role extends Base {
} }
export class SelectMenuInteraction<Cached extends CacheType = CacheType> extends MessageComponentInteraction<Cached> { export class SelectMenuInteraction<Cached extends CacheType = CacheType> extends MessageComponentInteraction<Cached> {
public constructor(client: Client, data: RawMessageSelectMenuInteractionData); public constructor(client: Client<true>, data: RawMessageSelectMenuInteractionData);
public get component(): CacheTypeReducer< public get component(): CacheTypeReducer<
Cached, Cached,
SelectMenuComponent, SelectMenuComponent,
@@ -2212,7 +2216,7 @@ export class Shard extends EventEmitter {
public worker: Worker | null; public worker: Worker | null;
public eval(script: string): Promise<unknown>; public eval(script: string): Promise<unknown>;
public eval<T>(fn: (client: Client) => T): Promise<T>; public eval<T>(fn: (client: Client) => T): Promise<T>;
public eval<T, P>(fn: (client: Client, context: Serialized<P>) => T, context: P): Promise<T>; public eval<T, P>(fn: (client: Client<true>, context: Serialized<P>) => T, context: P): Promise<T>;
public fetchClientValue(prop: string): Promise<unknown>; public fetchClientValue(prop: string): Promise<unknown>;
public kill(): void; public kill(): void;
public respawn(options?: { delay?: number; timeout?: number }): Promise<ChildProcess>; public respawn(options?: { delay?: number; timeout?: number }): Promise<ChildProcess>;
@@ -2231,7 +2235,7 @@ export class Shard extends EventEmitter {
} }
export class ShardClientUtil { export class ShardClientUtil {
private constructor(client: Client, mode: ShardingManagerMode); private constructor(client: Client<true>, mode: ShardingManagerMode);
private _handleMessage(message: unknown): void; private _handleMessage(message: unknown): void;
private _respond(type: string, message: unknown): void; private _respond(type: string, message: unknown): void;
private incrementMaxListeners(emitter: EventEmitter | ChildProcess): void; private incrementMaxListeners(emitter: EventEmitter | ChildProcess): void;
@@ -2245,11 +2249,11 @@ export class ShardClientUtil {
public broadcastEval<T>(fn: (client: Client) => Awaitable<T>): Promise<Serialized<T>[]>; public broadcastEval<T>(fn: (client: Client) => Awaitable<T>): Promise<Serialized<T>[]>;
public broadcastEval<T>(fn: (client: Client) => Awaitable<T>, options: { shard: number }): Promise<Serialized<T>>; public broadcastEval<T>(fn: (client: Client) => Awaitable<T>, options: { shard: number }): Promise<Serialized<T>>;
public broadcastEval<T, P>( public broadcastEval<T, P>(
fn: (client: Client, context: Serialized<P>) => Awaitable<T>, fn: (client: Client<true>, context: Serialized<P>) => Awaitable<T>,
options: { context: P }, options: { context: P },
): Promise<Serialized<T>[]>; ): Promise<Serialized<T>[]>;
public broadcastEval<T, P>( public broadcastEval<T, P>(
fn: (client: Client, context: Serialized<P>) => Awaitable<T>, fn: (client: Client<true>, context: Serialized<P>) => Awaitable<T>,
options: { context: P; shard: number }, options: { context: P; shard: number },
): Promise<Serialized<T>>; ): Promise<Serialized<T>>;
public fetchClientValues(prop: string): Promise<unknown[]>; public fetchClientValues(prop: string): Promise<unknown[]>;
@@ -2257,7 +2261,7 @@ export class ShardClientUtil {
public respawnAll(options?: MultipleShardRespawnOptions): Promise<void>; public respawnAll(options?: MultipleShardRespawnOptions): Promise<void>;
public send(message: unknown): Promise<void>; public send(message: unknown): Promise<void>;
public static singleton(client: Client, mode: ShardingManagerMode): ShardClientUtil; public static singleton(client: Client<true>, mode: ShardingManagerMode): ShardClientUtil;
public static shardIdForGuildId(guildId: Snowflake, shardCount: number): number; public static shardIdForGuildId(guildId: Snowflake, shardCount: number): number;
} }
@@ -2277,11 +2281,11 @@ export class ShardingManager extends EventEmitter {
public broadcastEval<T>(fn: (client: Client) => Awaitable<T>): Promise<Serialized<T>[]>; public broadcastEval<T>(fn: (client: Client) => Awaitable<T>): Promise<Serialized<T>[]>;
public broadcastEval<T>(fn: (client: Client) => Awaitable<T>, options: { shard: number }): Promise<Serialized<T>>; public broadcastEval<T>(fn: (client: Client) => Awaitable<T>, options: { shard: number }): Promise<Serialized<T>>;
public broadcastEval<T, P>( public broadcastEval<T, P>(
fn: (client: Client, context: Serialized<P>) => Awaitable<T>, fn: (client: Client<true>, context: Serialized<P>) => Awaitable<T>,
options: { context: P }, options: { context: P },
): Promise<Serialized<T>[]>; ): Promise<Serialized<T>[]>;
public broadcastEval<T, P>( public broadcastEval<T, P>(
fn: (client: Client, context: Serialized<P>) => Awaitable<T>, fn: (client: Client<true>, context: Serialized<P>) => Awaitable<T>,
options: { context: P; shard: number }, options: { context: P; shard: number },
): Promise<Serialized<T>>; ): Promise<Serialized<T>>;
public createShard(id: number): Shard; public createShard(id: number): Shard;
@@ -2321,7 +2325,7 @@ export class DirectoryChannel extends BaseChannel {
} }
export class StageInstance extends Base { export class StageInstance extends Base {
private constructor(client: Client, data: RawStageInstanceData, channel: StageChannel); private constructor(client: Client<true>, data: RawStageInstanceData, channel: StageChannel);
public id: Snowflake; public id: Snowflake;
public guildId: Snowflake; public guildId: Snowflake;
public channelId: Snowflake; public channelId: Snowflake;
@@ -2341,7 +2345,7 @@ export class StageInstance extends Base {
} }
export class Sticker extends Base { export class Sticker extends Base {
private constructor(client: Client, data: RawStickerData); private constructor(client: Client<true>, data: RawStickerData);
public get createdTimestamp(): number; public get createdTimestamp(): number;
public get createdAt(): Date; public get createdAt(): Date;
public available: boolean | null; public available: boolean | null;
@@ -2367,7 +2371,7 @@ export class Sticker extends Base {
} }
export class StickerPack extends Base { export class StickerPack extends Base {
private constructor(client: Client, data: RawStickerPackData); private constructor(client: Client<true>, data: RawStickerPackData);
public get createdTimestamp(): number; public get createdTimestamp(): number;
public get createdAt(): Date; public get createdAt(): Date;
public bannerId: Snowflake | null; public bannerId: Snowflake | null;
@@ -2382,7 +2386,7 @@ export class StickerPack extends Base {
} }
export class Sweepers { export class Sweepers {
public constructor(client: Client, options: SweeperOptions); public constructor(client: Client<true>, options: SweeperOptions);
public readonly client: Client; public readonly client: Client;
public intervals: Record<SweeperKey, NodeJS.Timeout | null>; public intervals: Record<SweeperKey, NodeJS.Timeout | null>;
public options: SweeperOptions; public options: SweeperOptions;
@@ -2451,7 +2455,7 @@ export class SystemChannelFlagsBitField extends BitField<SystemChannelFlagsStrin
} }
export class Team extends Base { export class Team extends Base {
private constructor(client: Client, data: RawTeamData); private constructor(client: Client<true>, data: RawTeamData);
public id: Snowflake; public id: Snowflake;
public name: string; public name: string;
public icon: string | null; public icon: string | null;
@@ -2500,7 +2504,7 @@ export class ThreadChannel extends TextBasedChannelMixin(BaseChannel, true, [
'createWebhook', 'createWebhook',
'setNSFW', 'setNSFW',
]) { ]) {
private constructor(guild: Guild, data?: RawThreadChannelData, client?: Client, fromInteraction?: boolean); private constructor(guild: Guild, data?: RawThreadChannelData, client?: Client<true>, fromInteraction?: boolean);
public archived: boolean | null; public archived: boolean | null;
public get archivedAt(): Date | null; public get archivedAt(): Date | null;
public archiveTimestamp: number | null; public archiveTimestamp: number | null;
@@ -2587,7 +2591,7 @@ export class Typing extends Base {
} }
export class User extends PartialTextBasedChannel(Base) { export class User extends PartialTextBasedChannel(Base) {
protected constructor(client: Client, data: RawUserData); protected constructor(client: Client<true>, data: RawUserData);
private _equals(user: APIUser): boolean; private _equals(user: APIUser): boolean;
public accentColor: number | null | undefined; public accentColor: number | null | undefined;
@@ -2664,7 +2668,7 @@ export function setPosition<T extends Channel | Role>(
position: number, position: number,
relative: boolean, relative: boolean,
sorted: Collection<Snowflake, T>, sorted: Collection<Snowflake, T>,
client: Client, client: Client<true>,
route: string, route: string,
reason?: string, reason?: string,
): Promise<{ id: Snowflake; position: number }[]>; ): Promise<{ id: Snowflake; position: number }[]>;
@@ -2689,7 +2693,7 @@ export interface CreateChannelOptions {
fromInteraction?: boolean; fromInteraction?: boolean;
} }
export function createChannel(client: Client, data: APIChannel, options?: CreateChannelOptions): Channel; export function createChannel(client: Client<true>, data: APIChannel, options?: CreateChannelOptions): Channel;
export function createComponent<T extends keyof MappedComponentTypes>( export function createComponent<T extends keyof MappedComponentTypes>(
data: APIMessageComponent & { type: T }, data: APIMessageComponent & { type: T },
@@ -2798,7 +2802,7 @@ export class VoiceState extends Base {
} }
export class Webhook extends WebhookMixin() { export class Webhook extends WebhookMixin() {
private constructor(client: Client, data?: RawWebhookData); private constructor(client: Client<true>, data?: RawWebhookData);
public avatar: string | null; public avatar: string | null;
public avatarURL(options?: ImageURLOptions): string | null; public avatarURL(options?: ImageURLOptions): string | null;
public channelId: Snowflake; public channelId: Snowflake;
@@ -2956,7 +2960,7 @@ export class WebSocketShard extends EventEmitter {
} }
export class Widget extends Base { export class Widget extends Base {
private constructor(client: Client, data: RawWidgetData); private constructor(client: Client<true>, data: RawWidgetData);
private _patch(data: RawWidgetData): void; private _patch(data: RawWidgetData): void;
public fetch(): Promise<Widget>; public fetch(): Promise<Widget>;
public id: Snowflake; public id: Snowflake;
@@ -2967,7 +2971,7 @@ export class Widget extends Base {
} }
export class WidgetMember extends Base { export class WidgetMember extends Base {
private constructor(client: Client, data: RawWidgetMemberData); private constructor(client: Client<true>, data: RawWidgetMemberData);
public id: string; public id: string;
public username: string; public username: string;
public discriminator: string; public discriminator: string;
@@ -3194,7 +3198,7 @@ export abstract class BaseManager {
} }
export abstract class DataManager<K, Holds, R> extends BaseManager { export abstract class DataManager<K, Holds, R> extends BaseManager {
protected constructor(client: Client, holds: Constructable<Holds>); protected constructor(client: Client<true>, holds: Constructable<Holds>);
public readonly holds: Constructable<Holds>; public readonly holds: Constructable<Holds>;
public get cache(): Collection<K, Holds>; public get cache(): Collection<K, Holds>;
public resolve(resolvable: Holds): Holds; public resolve(resolvable: Holds): Holds;
@@ -3205,7 +3209,7 @@ export abstract class DataManager<K, Holds, R> extends BaseManager {
} }
export abstract class CachedManager<K, Holds, R> extends DataManager<K, Holds, R> { export abstract class CachedManager<K, Holds, R> extends DataManager<K, Holds, R> {
protected constructor(client: Client, holds: Constructable<Holds>); protected constructor(client: Client<true>, holds: Constructable<Holds>);
private _add(data: unknown, cache?: boolean, { id, extras }?: { id: K; extras: unknown[] }): Holds; private _add(data: unknown, cache?: boolean, { id, extras }?: { id: K; extras: unknown[] }): Holds;
} }
@@ -3219,7 +3223,7 @@ export class ApplicationCommandManager<
PermissionsOptionsExtras = { guild: GuildResolvable }, PermissionsOptionsExtras = { guild: GuildResolvable },
PermissionsGuildType = null, PermissionsGuildType = null,
> extends CachedManager<Snowflake, ApplicationCommandScope, ApplicationCommandResolvable> { > extends CachedManager<Snowflake, ApplicationCommandScope, ApplicationCommandResolvable> {
protected constructor(client: Client, iterable?: Iterable<unknown>); protected constructor(client: Client<true>, iterable?: Iterable<unknown>);
public permissions: ApplicationCommandPermissionsManager< public permissions: ApplicationCommandPermissionsManager<
{ command?: ApplicationCommandResolvable } & PermissionsOptionsExtras, { command?: ApplicationCommandResolvable } & PermissionsOptionsExtras,
{ command: ApplicationCommandResolvable } & PermissionsOptionsExtras, { command: ApplicationCommandResolvable } & PermissionsOptionsExtras,
@@ -3307,7 +3311,7 @@ export class ApplicationCommandPermissionsManager<
} }
export class BaseGuildEmojiManager extends CachedManager<Snowflake, GuildEmoji, EmojiResolvable> { export class BaseGuildEmojiManager extends CachedManager<Snowflake, GuildEmoji, EmojiResolvable> {
protected constructor(client: Client, iterable?: Iterable<RawGuildEmojiData>); protected constructor(client: Client<true>, iterable?: Iterable<RawGuildEmojiData>);
public resolveIdentifier(emoji: EmojiIdentifierResolvable): string | null; public resolveIdentifier(emoji: EmojiIdentifierResolvable): string | null;
} }
@@ -3323,7 +3327,7 @@ export class CategoryChannelChildManager extends DataManager<Snowflake, Category
} }
export class ChannelManager extends CachedManager<Snowflake, Channel, ChannelResolvable> { export class ChannelManager extends CachedManager<Snowflake, Channel, ChannelResolvable> {
private constructor(client: Client, iterable: Iterable<RawChannelData>); private constructor(client: Client<true>, iterable: Iterable<RawChannelData>);
public fetch(id: Snowflake, options?: FetchChannelOptions): Promise<Channel | null>; public fetch(id: Snowflake, options?: FetchChannelOptions): Promise<Channel | null>;
} }
@@ -3405,7 +3409,7 @@ export class GuildEmojiRoleManager extends DataManager<Snowflake, Role, RoleReso
} }
export class GuildManager extends CachedManager<Snowflake, Guild, GuildResolvable> { export class GuildManager extends CachedManager<Snowflake, Guild, GuildResolvable> {
private constructor(client: Client, iterable?: Iterable<RawGuildData>); private constructor(client: Client<true>, iterable?: Iterable<RawGuildData>);
public create(options: GuildCreateOptions): Promise<Guild>; public create(options: GuildCreateOptions): Promise<Guild>;
public fetch(options: Snowflake | FetchGuildOptions): Promise<Guild>; public fetch(options: Snowflake | FetchGuildOptions): Promise<Guild>;
public fetch(options?: FetchGuildsOptions): Promise<Collection<Snowflake, OAuth2Guild>>; public fetch(options?: FetchGuildsOptions): Promise<Collection<Snowflake, OAuth2Guild>>;
@@ -3543,7 +3547,7 @@ export class PermissionOverwriteManager extends CachedManager<
PermissionOverwrites, PermissionOverwrites,
PermissionOverwriteResolvable PermissionOverwriteResolvable
> { > {
private constructor(client: Client, iterable?: Iterable<RawPermissionOverwriteData>); private constructor(client: Client<true>, iterable?: Iterable<RawPermissionOverwriteData>);
public set( public set(
overwrites: readonly OverwriteResolvable[] | Collection<Snowflake, OverwriteResolvable>, overwrites: readonly OverwriteResolvable[] | Collection<Snowflake, OverwriteResolvable>,
reason?: string, reason?: string,
@@ -3568,7 +3572,7 @@ export class PermissionOverwriteManager extends CachedManager<
} }
export class PresenceManager extends CachedManager<Snowflake, Presence, PresenceResolvable> { export class PresenceManager extends CachedManager<Snowflake, Presence, PresenceResolvable> {
private constructor(client: Client, iterable?: Iterable<RawPresenceData>); private constructor(client: Client<true>, iterable?: Iterable<RawPresenceData>);
} }
export class ReactionManager extends CachedManager<Snowflake | string, MessageReaction, MessageReactionResolvable> { export class ReactionManager extends CachedManager<Snowflake | string, MessageReaction, MessageReactionResolvable> {
@@ -3632,7 +3636,7 @@ export class ThreadMemberManager extends CachedManager<Snowflake, ThreadMember,
} }
export class UserManager extends CachedManager<Snowflake, User, UserResolvable> { export class UserManager extends CachedManager<Snowflake, User, UserResolvable> {
private constructor(client: Client, iterable?: Iterable<RawUserData>); private constructor(client: Client<true>, iterable?: Iterable<RawUserData>);
private dmChannel(userId: Snowflake): DMChannel | null; private dmChannel(userId: Snowflake): DMChannel | null;
public createDM(user: UserResolvable, options?: BaseFetchOptions): Promise<DMChannel>; public createDM(user: UserResolvable, options?: BaseFetchOptions): Promise<DMChannel>;
public deleteDM(user: UserResolvable): Promise<DMChannel>; public deleteDM(user: UserResolvable): Promise<DMChannel>;
@@ -5332,7 +5336,7 @@ export type Partialize<
M extends keyof T | null = null, M extends keyof T | null = null,
E extends keyof T | '' = '', E extends keyof T | '' = '',
> = { > = {
readonly client: Client; readonly client: Client<true>;
id: Snowflake; id: Snowflake;
partial: true; partial: true;
} & { } & {

View File

@@ -165,8 +165,383 @@ const guildCommandId = '234567890123456789'; // example id
declare const slashCommandBuilder: SlashCommandBuilder; declare const slashCommandBuilder: SlashCommandBuilder;
declare const contextMenuCommandBuilder: ContextMenuCommandBuilder; declare const contextMenuCommandBuilder: ContextMenuCommandBuilder;
client.on('ready', async () => { client.on('channelCreate', ({ client }) => expectType<Client<true>>(client));
console.log(`Client is logged in as ${client.user!.tag} and ready!`); client.on('channelDelete', ({ client }) => expectType<Client<true>>(client));
client.on('channelPinsUpdate', ({ client }) => expectType<Client<true>>(client));
client.on('channelUpdate', ({ client: oldClient }, { client: newClient }) => {
expectType<Client<true>>(oldClient);
expectType<Client<true>>(newClient);
});
client.on('emojiCreate', ({ client }) => expectType<Client<true>>(client));
client.on('emojiDelete', ({ client }) => expectType<Client<true>>(client));
client.on('emojiUpdate', ({ client: oldClient }, { client: newClient }) => {
expectType<Client<true>>(oldClient);
expectType<Client<true>>(newClient);
});
client.on('guildBanAdd', ({ client }) => expectType<Client<true>>(client));
client.on('guildBanRemove', ({ client }) => expectType<Client<true>>(client));
client.on('guildDelete', ({ client }) => expectType<Client<true>>(client));
client.on('guildIntegrationsUpdate', ({ client }) => expectType<Client<true>>(client));
client.on('guildMemberAdd', ({ client }) => expectType<Client<true>>(client));
client.on('guildMemberAvailable', ({ client }) => expectType<Client<true>>(client));
client.on('guildMemberRemove', member => {
expectType<Client<true>>(member.client);
if (member.partial) return expectType<null>(member.joinedAt);
expectType<Date | null>(member.joinedAt);
});
client.on('guildMembersChunk', (members, { client }) => {
expectType<Client<true>>(members.first()!.client);
expectType<Client<true>>(client);
});
client.on('guildMemberUpdate', ({ client: oldClient }, { client: newClient }) => {
expectType<Client<true>>(oldClient);
expectType<Client<true>>(newClient);
});
client.on('guildScheduledEventCreate', ({ client }) => expectType<Client<true>>(client));
client.on('guildScheduledEventDelete', ({ client }) => expectType<Client<true>>(client));
client.on('guildScheduledEventUpdate', (oldGuildScheduledEvent, { client }) => {
expectType<Client<true>>(oldGuildScheduledEvent!.client);
expectType<Client<true>>(client);
});
client.on('guildScheduledEventUserAdd', ({ client: oldClient }, { client: newClient }) => {
expectType<Client<true>>(oldClient);
expectType<Client<true>>(newClient);
});
client.on('guildScheduledEventUserRemove', ({ client: oldClient }, { client: newClient }) => {
expectType<Client<true>>(oldClient);
expectType<Client<true>>(newClient);
});
client.on('guildUnavailable', ({ client }) => expectType<Client<true>>(client));
client.on('guildUpdate', ({ client: oldClient }, { client: newClient }) => {
expectType<Client<true>>(oldClient);
expectType<Client<true>>(newClient);
});
client.on('interactionCreate', async interaction => {
expectType<Client<true>>(interaction.client);
expectType<Snowflake | null>(interaction.guildId);
expectType<Snowflake | null>(interaction.channelId);
expectType<GuildMember | APIInteractionGuildMember | null>(interaction.member);
if (interaction.type === InteractionType.MessageComponent) {
expectType<Snowflake>(interaction.channelId);
}
if (interaction.type !== InteractionType.ApplicationCommand) return;
void new ActionRowBuilder<MessageActionRowComponentBuilder>();
const button = new ButtonBuilder();
const actionRow = new ActionRowBuilder<MessageActionRowComponentBuilder>({
type: ComponentType.ActionRow,
components: [button.toJSON()],
});
actionRow.toJSON();
await interaction.reply({ content: 'Hi!', components: [actionRow] });
// @ts-expect-error
interaction.reply({ content: 'Hi!', components: [[button]] });
void new ActionRowBuilder({});
// @ts-expect-error
await interaction.reply({ content: 'Hi!', components: [button] });
await interaction.reply({
content: 'test',
components: [
{
components: [
{
custom_id: 'abc',
label: 'abc',
style: ButtonStyle.Primary,
type: ComponentType.Button,
},
],
type: ComponentType.ActionRow,
},
],
});
// This is for testing never type resolution
if (!interaction.inGuild()) {
return;
}
if (interaction.inRawGuild()) {
expectNotType<never>(interaction);
return;
}
if (interaction.inCachedGuild()) {
expectNotType<never>(interaction);
return;
}
});
client.on('inviteCreate', ({ client }) => expectType<Client<true>>(client));
client.on('inviteDelete', ({ client }) => expectType<Client<true>>(client));
// This is to check that stuff is the right type
declare const assertIsMessage: (m: Promise<Message>) => void;
client.on('messageCreate', async message => {
const { client, channel } = message;
expectType<Client<true>>(client);
assertIsMessage(channel.send('string'));
assertIsMessage(channel.send({}));
assertIsMessage(channel.send({ embeds: [] }));
const attachment = new AttachmentBuilder('file.png');
const embed = new EmbedBuilder();
assertIsMessage(channel.send({ files: [attachment] }));
assertIsMessage(channel.send({ embeds: [embed] }));
assertIsMessage(channel.send({ embeds: [embed], files: [attachment] }));
if (message.inGuild()) {
expectAssignable<Message<true>>(message);
const component = await message.awaitMessageComponent({ componentType: ComponentType.Button });
expectType<ButtonInteraction<'cached'>>(component);
expectType<Message<true>>(await component.reply({ fetchReply: true }));
const buttonCollector = message.createMessageComponentCollector({ componentType: ComponentType.Button });
expectType<InteractionCollector<ButtonInteraction<'cached'>>>(buttonCollector);
expectAssignable<
(
test: ButtonInteraction<'cached'>,
items: Collection<Snowflake, ButtonInteraction<'cached'>>,
) => boolean | Promise<boolean>
>(buttonCollector.filter);
expectType<GuildTextBasedChannel>(message.channel);
expectType<Guild>(message.guild);
expectType<GuildMember | null>(message.member);
}
expectType<TextBasedChannel>(message.channel);
expectNotType<GuildTextBasedChannel>(message.channel);
// @ts-expect-error
channel.send();
// @ts-expect-error
channel.send({ another: 'property' });
// Check collector creations.
// Verify that buttons interactions are inferred.
const buttonCollector = message.createMessageComponentCollector({ componentType: ComponentType.Button });
expectAssignable<Promise<ButtonInteraction>>(message.awaitMessageComponent({ componentType: ComponentType.Button }));
expectAssignable<Promise<ButtonInteraction>>(channel.awaitMessageComponent({ componentType: ComponentType.Button }));
expectAssignable<InteractionCollector<ButtonInteraction>>(buttonCollector);
// Verify that select menus interaction are inferred.
const selectMenuCollector = message.createMessageComponentCollector({ componentType: ComponentType.SelectMenu });
expectAssignable<Promise<SelectMenuInteraction>>(
message.awaitMessageComponent({ componentType: ComponentType.SelectMenu }),
);
expectAssignable<Promise<SelectMenuInteraction>>(
channel.awaitMessageComponent({ componentType: ComponentType.SelectMenu }),
);
expectAssignable<InteractionCollector<SelectMenuInteraction>>(selectMenuCollector);
// Verify that message component interactions are default collected types.
const defaultCollector = message.createMessageComponentCollector();
expectAssignable<Promise<MessageComponentInteraction>>(message.awaitMessageComponent());
expectAssignable<Promise<MessageComponentInteraction>>(channel.awaitMessageComponent());
expectAssignable<InteractionCollector<CollectedMessageInteraction>>(defaultCollector);
// Verify that additional options don't affect default collector types.
const semiDefaultCollector = message.createMessageComponentCollector({ time: 10000 });
expectType<InteractionCollector<CollectedMessageInteraction>>(semiDefaultCollector);
const semiDefaultCollectorChannel = message.createMessageComponentCollector({ time: 10000 });
expectType<InteractionCollector<CollectedMessageInteraction>>(semiDefaultCollectorChannel);
// Verify that interaction collector options can't be used.
message.createMessageComponentCollector({
// @ts-expect-error
interactionType: InteractionType.ApplicationCommand,
});
// Make sure filter parameters are properly inferred.
message.createMessageComponentCollector({
filter: i => {
expectType<CollectedMessageInteraction>(i);
return true;
},
});
message.createMessageComponentCollector({
componentType: ComponentType.Button,
filter: i => {
expectType<ButtonInteraction>(i);
return true;
},
});
message.createMessageComponentCollector({
componentType: ComponentType.SelectMenu,
filter: i => {
expectType<SelectMenuInteraction>(i);
return true;
},
});
message.awaitMessageComponent({
filter: i => {
expectType<CollectedMessageInteraction>(i);
return true;
},
});
message.awaitMessageComponent({
componentType: ComponentType.Button,
filter: i => {
expectType<ButtonInteraction>(i);
return true;
},
});
message.awaitMessageComponent({
componentType: ComponentType.SelectMenu,
filter: i => {
expectType<SelectMenuInteraction>(i);
return true;
},
});
const webhook = await message.fetchWebhook();
if (webhook.isChannelFollower()) {
expectAssignable<Guild | APIPartialGuild>(webhook.sourceGuild);
expectAssignable<NewsChannel | APIPartialChannel>(webhook.sourceChannel);
} else if (webhook.isIncoming()) {
expectType<string>(webhook.token);
}
expectNotType<Guild | APIPartialGuild>(webhook.sourceGuild);
expectNotType<NewsChannel | APIPartialChannel>(webhook.sourceChannel);
expectNotType<string>(webhook.token);
channel.awaitMessageComponent({
filter: i => {
expectType<CollectedMessageInteraction<'cached'>>(i);
return true;
},
});
channel.awaitMessageComponent({
componentType: ComponentType.Button,
filter: i => {
expectType<ButtonInteraction<'cached'>>(i);
return true;
},
});
channel.awaitMessageComponent({
componentType: ComponentType.SelectMenu,
filter: i => {
expectType<SelectMenuInteraction<'cached'>>(i);
return true;
},
});
// Check that both builders and builder data can be sent in messages
const row = new ActionRowBuilder<MessageActionRowComponentBuilder>();
const buttonsRow: ActionRowData<MessageActionRowComponentData> = {
type: ComponentType.ActionRow,
components: [
new ButtonBuilder(),
{ type: ComponentType.Button, label: 'test', style: ButtonStyle.Primary, customId: 'test' },
{
type: ComponentType.Button,
label: 'another test',
style: ButtonStyle.Link,
url: 'https://discord.js.org',
},
],
};
const selectsRow: ActionRowData<MessageActionRowComponentData> = {
type: ComponentType.ActionRow,
components: [
new SelectMenuBuilder(),
{
type: ComponentType.SelectMenu,
label: 'select menu',
options: [{ label: 'test', value: 'test' }],
customId: 'test',
},
],
};
const embedData = { description: 'test', color: 0xff0000 };
channel.send({ components: [row, buttonsRow, selectsRow], embeds: [embed, embedData] });
});
client.on('messageDelete', ({ client }) => expectType<Client<true>>(client));
client.on('messageDeleteBulk', (messages, { client }) => {
expectType<Client<true>>(messages.first()!.client);
expectType<Client<true>>(client);
});
client.on('messageReactionAdd', async (reaction, { client }) => {
expectType<Client<true>>(reaction.client);
expectType<Client<true>>(client);
if (reaction.partial) {
expectType<null>(reaction.count);
reaction = await reaction.fetch();
}
expectType<number>(reaction.count);
if (reaction.message.partial) return expectType<string | null>(reaction.message.content);
expectType<string>(reaction.message.content);
});
client.on('messageReactionRemove', ({ client: oldClient }, { client: newClient }) => {
expectType<Client<true>>(oldClient);
expectType<Client<true>>(newClient);
});
client.on('messageReactionRemoveAll', async (message, reactions) => {
console.log(`messageReactionRemoveAll - id: ${message.id} (${message.id.length})`);
if (message.partial) message = await message.fetch();
console.log(`messageReactionRemoveAll - content: ${message.content}`);
expectType<Client<true>>(message.client);
expectType<Client<true>>(reactions.first()!.client);
});
client.on('messageReactionRemoveEmoji', ({ client }) => expectType<Client<true>>(client));
client.on('messageUpdate', ({ client: oldClient }, { client: newClient }) => {
expectType<Client<true>>(oldClient);
expectType<Client<true>>(newClient);
});
client.on('presenceUpdate', (oldPresence, { client }) => {
expectType<Client<true>>(oldPresence!.client);
expectType<Client<true>>(client);
});
client.on('ready', async client => {
expectType<Client<true>>(client);
console.log(`Client is logged in as ${client.user.tag} and ready!`);
// Test fetching all global commands and ones from one guild // Test fetching all global commands and ones from one guild
expectType<Collection<string, ApplicationCommand<{ guild: GuildResolvable }>>>( expectType<Collection<string, ApplicationCommand<{ guild: GuildResolvable }>>>(
@@ -639,7 +1014,94 @@ client.on('ready', async () => {
}); });
}); });
client.on('roleCreate', ({ client }) => expectType<Client<true>>(client));
client.on('roleDelete', ({ client }) => expectType<Client<true>>(client));
client.on('roleUpdate', ({ client: oldClient }, { client: newClient }) => {
expectType<Client<true>>(oldClient);
expectType<Client<true>>(newClient);
});
client.on('stageInstanceCreate', ({ client }) => expectType<Client<true>>(client));
client.on('stageInstanceDelete', ({ client }) => expectType<Client<true>>(client));
client.on('stageInstanceUpdate', (oldStageInstance, { client }) => {
expectType<Client<true>>(oldStageInstance!.client);
expectType<Client<true>>(client);
});
client.on('stickerCreate', ({ client }) => expectType<Client<true>>(client));
client.on('stickerDelete', ({ client }) => expectType<Client<true>>(client));
client.on('stickerUpdate', ({ client: oldClient }, { client: newClient }) => {
expectType<Client<true>>(oldClient);
expectType<Client<true>>(newClient);
});
client.on('threadCreate', thread => {
expectType<Client<true>>(thread.client);
if (thread.type === ChannelType.GuildPrivateThread) {
expectType<number>(thread.createdTimestamp);
expectType<Date>(thread.createdAt);
} else {
expectType<number | null>(thread.createdTimestamp);
expectType<Date | null>(thread.createdAt);
}
});
client.on('threadDelete', ({ client }) => expectType<Client<true>>(client));
client.on('threadListSync', (threads, { client }) => {
expectType<Client<true>>(threads.first()!.client);
expectType<Client<true>>(client);
});
client.on('threadMembersUpdate', (addedMembers, removedMembers, thread) => {
expectType<Client<true>>(addedMembers.first()!.client);
expectType<Client<true>>(removedMembers.first()!.client);
expectType<Client<true>>(thread.client);
expectType<Collection<Snowflake, ThreadMember>>(addedMembers);
expectType<Collection<Snowflake, ThreadMember | PartialThreadMember>>(removedMembers);
expectType<AnyThreadChannel>(thread);
const left = removedMembers.first();
if (!left) return;
if (left.partial) {
expectType<PartialThreadMember>(left);
expectType<null>(left.flags);
} else {
expectType<ThreadMember>(left);
expectType<ThreadMemberFlagsBitField>(left.flags);
}
});
client.on('threadMemberUpdate', ({ client: oldClient }, { client: newClient }) => {
expectType<Client<true>>(oldClient);
expectType<Client<true>>(newClient);
});
client.on('threadUpdate', ({ client: oldClient }, { client: newClient }) => {
expectType<Client<true>>(oldClient);
expectType<Client<true>>(newClient);
});
client.on('typingStart', ({ client }) => expectType<Client<true>>(client));
client.on('userUpdate', ({ client: oldClient }, { client: newClient }) => {
expectType<Client<true>>(oldClient);
expectType<Client<true>>(newClient);
});
client.on('voiceStateUpdate', ({ client: oldClient }, { client: newClient }) => {
expectType<Client<true>>(oldClient);
expectType<Client<true>>(newClient);
});
client.on('webhookUpdate', ({ client }) => expectType<Client<true>>(client));
client.on('guildCreate', async g => { client.on('guildCreate', async g => {
expectType<Client<true>>(g.client);
const channel = g.channels.cache.random(); const channel = g.channels.cache.random();
if (!channel) return; if (!channel) return;
@@ -704,290 +1166,8 @@ client.on('guildCreate', async g => {
); );
}); });
client.on('messageReactionRemoveAll', async message => {
console.log(`messageReactionRemoveAll - id: ${message.id} (${message.id.length})`);
if (message.partial) message = await message.fetch();
console.log(`messageReactionRemoveAll - content: ${message.content}`);
});
// This is to check that stuff is the right type
declare const assertIsMessage: (m: Promise<Message>) => void;
client.on('messageCreate', async message => {
const { channel } = message;
assertIsMessage(channel.send('string'));
assertIsMessage(channel.send({}));
assertIsMessage(channel.send({ embeds: [] }));
const attachment = new AttachmentBuilder('file.png');
const embed = new EmbedBuilder();
assertIsMessage(channel.send({ files: [attachment] }));
assertIsMessage(channel.send({ embeds: [embed] }));
assertIsMessage(channel.send({ embeds: [embed], files: [attachment] }));
if (message.inGuild()) {
expectAssignable<Message<true>>(message);
const component = await message.awaitMessageComponent({ componentType: ComponentType.Button });
expectType<ButtonInteraction<'cached'>>(component);
expectType<Message<true>>(await component.reply({ fetchReply: true }));
const buttonCollector = message.createMessageComponentCollector({ componentType: ComponentType.Button });
expectType<InteractionCollector<ButtonInteraction<'cached'>>>(buttonCollector);
expectAssignable<
(
test: ButtonInteraction<'cached'>,
items: Collection<Snowflake, ButtonInteraction<'cached'>>,
) => boolean | Promise<boolean>
>(buttonCollector.filter);
expectType<GuildTextBasedChannel>(message.channel);
expectType<Guild>(message.guild);
expectType<GuildMember | null>(message.member);
}
expectType<TextBasedChannel>(message.channel);
expectNotType<GuildTextBasedChannel>(message.channel);
// @ts-expect-error
channel.send();
// @ts-expect-error
channel.send({ another: 'property' });
// Check collector creations.
// Verify that buttons interactions are inferred.
const buttonCollector = message.createMessageComponentCollector({ componentType: ComponentType.Button });
expectAssignable<Promise<ButtonInteraction>>(message.awaitMessageComponent({ componentType: ComponentType.Button }));
expectAssignable<Promise<ButtonInteraction>>(channel.awaitMessageComponent({ componentType: ComponentType.Button }));
expectAssignable<InteractionCollector<ButtonInteraction>>(buttonCollector);
// Verify that select menus interaction are inferred.
const selectMenuCollector = message.createMessageComponentCollector({ componentType: ComponentType.SelectMenu });
expectAssignable<Promise<SelectMenuInteraction>>(
message.awaitMessageComponent({ componentType: ComponentType.SelectMenu }),
);
expectAssignable<Promise<SelectMenuInteraction>>(
channel.awaitMessageComponent({ componentType: ComponentType.SelectMenu }),
);
expectAssignable<InteractionCollector<SelectMenuInteraction>>(selectMenuCollector);
// Verify that message component interactions are default collected types.
const defaultCollector = message.createMessageComponentCollector();
expectAssignable<Promise<MessageComponentInteraction>>(message.awaitMessageComponent());
expectAssignable<Promise<MessageComponentInteraction>>(channel.awaitMessageComponent());
expectAssignable<InteractionCollector<CollectedMessageInteraction>>(defaultCollector);
// Verify that additional options don't affect default collector types.
const semiDefaultCollector = message.createMessageComponentCollector({ time: 10000 });
expectType<InteractionCollector<CollectedMessageInteraction>>(semiDefaultCollector);
const semiDefaultCollectorChannel = message.createMessageComponentCollector({ time: 10000 });
expectType<InteractionCollector<CollectedMessageInteraction>>(semiDefaultCollectorChannel);
// Verify that interaction collector options can't be used.
message.createMessageComponentCollector({
// @ts-expect-error
interactionType: InteractionType.ApplicationCommand,
});
// Make sure filter parameters are properly inferred.
message.createMessageComponentCollector({
filter: i => {
expectType<CollectedMessageInteraction>(i);
return true;
},
});
message.createMessageComponentCollector({
componentType: ComponentType.Button,
filter: i => {
expectType<ButtonInteraction>(i);
return true;
},
});
message.createMessageComponentCollector({
componentType: ComponentType.SelectMenu,
filter: i => {
expectType<SelectMenuInteraction>(i);
return true;
},
});
message.awaitMessageComponent({
filter: i => {
expectType<CollectedMessageInteraction>(i);
return true;
},
});
message.awaitMessageComponent({
componentType: ComponentType.Button,
filter: i => {
expectType<ButtonInteraction>(i);
return true;
},
});
message.awaitMessageComponent({
componentType: ComponentType.SelectMenu,
filter: i => {
expectType<SelectMenuInteraction>(i);
return true;
},
});
const webhook = await message.fetchWebhook();
if (webhook.isChannelFollower()) {
expectAssignable<Guild | APIPartialGuild>(webhook.sourceGuild);
expectAssignable<NewsChannel | APIPartialChannel>(webhook.sourceChannel);
} else if (webhook.isIncoming()) {
expectType<string>(webhook.token);
}
expectNotType<Guild | APIPartialGuild>(webhook.sourceGuild);
expectNotType<NewsChannel | APIPartialChannel>(webhook.sourceChannel);
expectNotType<string>(webhook.token);
channel.awaitMessageComponent({
filter: i => {
expectType<CollectedMessageInteraction<'cached'>>(i);
return true;
},
});
channel.awaitMessageComponent({
componentType: ComponentType.Button,
filter: i => {
expectType<ButtonInteraction<'cached'>>(i);
return true;
},
});
channel.awaitMessageComponent({
componentType: ComponentType.SelectMenu,
filter: i => {
expectType<SelectMenuInteraction<'cached'>>(i);
return true;
},
});
// Check that both builders and builder data can be sent in messages
const row = new ActionRowBuilder<MessageActionRowComponentBuilder>();
const buttonsRow: ActionRowData<MessageActionRowComponentData> = {
type: ComponentType.ActionRow,
components: [
new ButtonBuilder(),
{ type: ComponentType.Button, label: 'test', style: ButtonStyle.Primary, customId: 'test' },
{
type: ComponentType.Button,
label: 'another test',
style: ButtonStyle.Link,
url: 'https://discord.js.org',
},
],
};
const selectsRow: ActionRowData<MessageActionRowComponentData> = {
type: ComponentType.ActionRow,
components: [
new SelectMenuBuilder(),
{
type: ComponentType.SelectMenu,
label: 'select menu',
options: [{ label: 'test', value: 'test' }],
customId: 'test',
},
],
};
const embedData = { description: 'test', color: 0xff0000 };
channel.send({ components: [row, buttonsRow, selectsRow], embeds: [embed, embedData] });
});
client.on('threadCreate', thread => {
if (thread.type === ChannelType.GuildPrivateThread) {
expectType<number>(thread.createdTimestamp);
expectType<Date>(thread.createdAt);
} else {
expectType<number | null>(thread.createdTimestamp);
expectType<Date | null>(thread.createdAt);
}
});
client.on('threadMembersUpdate', (addedMembers, removedMembers, thread) => {
expectType<Collection<Snowflake, ThreadMember>>(addedMembers);
expectType<Collection<Snowflake, ThreadMember | PartialThreadMember>>(removedMembers);
expectType<AnyThreadChannel>(thread);
const left = removedMembers.first();
if (!left) return;
if (left.partial) {
expectType<PartialThreadMember>(left);
expectType<null>(left.flags);
} else {
expectType<ThreadMember>(left);
expectType<ThreadMemberFlagsBitField>(left.flags);
}
});
client.on('interactionCreate', async interaction => {
expectType<Snowflake | null>(interaction.guildId);
expectType<Snowflake | null>(interaction.channelId);
expectType<GuildMember | APIInteractionGuildMember | null>(interaction.member);
if (interaction.type === InteractionType.MessageComponent) {
expectType<Snowflake>(interaction.channelId);
}
if (interaction.type !== InteractionType.ApplicationCommand) return;
void new ActionRowBuilder<MessageActionRowComponentBuilder>();
const button = new ButtonBuilder();
const actionRow = new ActionRowBuilder<MessageActionRowComponentBuilder>({
type: ComponentType.ActionRow,
components: [button.toJSON()],
});
actionRow.toJSON();
await interaction.reply({ content: 'Hi!', components: [actionRow] });
// @ts-expect-error
interaction.reply({ content: 'Hi!', components: [[button]] });
void new ActionRowBuilder({});
// @ts-expect-error
await interaction.reply({ content: 'Hi!', components: [button] });
await interaction.reply({
content: 'test',
components: [
{
components: [
{
custom_id: 'abc',
label: 'abc',
style: ButtonStyle.Primary,
type: ComponentType.Button,
},
],
type: ComponentType.ActionRow,
},
],
});
});
client.login('absolutely-valid-token'); client.login('absolutely-valid-token');
// Test client conditional types
client.on('ready', client => {
expectType<Client<true>>(client);
});
declare const loggedInClient: Client<true>; declare const loggedInClient: Client<true>;
expectType<ClientApplication>(loggedInClient.application); expectType<ClientApplication>(loggedInClient.application);
expectType<Date>(loggedInClient.readyAt); expectType<Date>(loggedInClient.readyAt);
@@ -1289,22 +1469,6 @@ if (typing.inGuild()) {
expectType<Guild>(typing.guild); expectType<Guild>(typing.guild);
} }
// Test partials structures
client.on('guildMemberRemove', member => {
if (member.partial) return expectType<null>(member.joinedAt);
expectType<Date | null>(member.joinedAt);
});
client.on('messageReactionAdd', async reaction => {
if (reaction.partial) {
expectType<null>(reaction.count);
reaction = await reaction.fetch();
}
expectType<number>(reaction.count);
if (reaction.message.partial) return expectType<string | null>(reaction.message.content);
expectType<string>(reaction.message.content);
});
// Test interactions // Test interactions
declare const interaction: Interaction; declare const interaction: Interaction;
declare const booleanValue: boolean; declare const booleanValue: boolean;
@@ -1314,23 +1478,6 @@ if (interaction.inGuild()) {
expectType<Snowflake | null>(interaction.guildId); expectType<Snowflake | null>(interaction.guildId);
} }
client.on('interactionCreate', interaction => {
// This is for testing never type resolution
if (!interaction.inGuild()) {
return;
}
if (interaction.inRawGuild()) {
expectNotType<never>(interaction);
return;
}
if (interaction.inCachedGuild()) {
expectNotType<never>(interaction);
return;
}
});
client.on('interactionCreate', async interaction => { client.on('interactionCreate', async interaction => {
if (interaction.type === InteractionType.MessageComponent) { if (interaction.type === InteractionType.MessageComponent) {
expectType<SelectMenuInteraction | ButtonInteraction>(interaction); expectType<SelectMenuInteraction | ButtonInteraction>(interaction);