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

View File

@@ -165,8 +165,383 @@ const guildCommandId = '234567890123456789'; // example id
declare const slashCommandBuilder: SlashCommandBuilder;
declare const contextMenuCommandBuilder: ContextMenuCommandBuilder;
client.on('ready', async () => {
console.log(`Client is logged in as ${client.user!.tag} and ready!`);
client.on('channelCreate', ({ client }) => expectType<Client<true>>(client));
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
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 => {
expectType<Client<true>>(g.client);
const channel = g.channels.cache.random();
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');
// Test client conditional types
client.on('ready', client => {
expectType<Client<true>>(client);
});
declare const loggedInClient: Client<true>;
expectType<ClientApplication>(loggedInClient.application);
expectType<Date>(loggedInClient.readyAt);
@@ -1289,22 +1469,6 @@ if (typing.inGuild()) {
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
declare const interaction: Interaction;
declare const booleanValue: boolean;
@@ -1314,23 +1478,6 @@ if (interaction.inGuild()) {
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 => {
if (interaction.type === InteractionType.MessageComponent) {
expectType<SelectMenuInteraction | ButtonInteraction>(interaction);