mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-16 11:33:30 +01:00
typings: Allow message component interaction collectors to infer collected interaction types (#6476)
This commit is contained in:
82
typings/index.d.ts
vendored
82
typings/index.d.ts
vendored
@@ -1103,6 +1103,46 @@ export class LimitedCollection<K, V> extends Collection<K, V> {
|
|||||||
public static filterByLifetime<K, V>(options?: LifetimeFilterOptions<K, V>): SweepFilter<K, V>;
|
public static filterByLifetime<K, V>(options?: LifetimeFilterOptions<K, V>): SweepFilter<K, V>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is a general conditional type utility that allows for specific union members to be extracted given
|
||||||
|
// a tagged union.
|
||||||
|
type TaggedUnion<T, K extends keyof T, V extends T[K]> = T extends Record<K, V>
|
||||||
|
? T
|
||||||
|
: T extends Record<K, infer U>
|
||||||
|
? V extends U
|
||||||
|
? T
|
||||||
|
: never
|
||||||
|
: never;
|
||||||
|
|
||||||
|
// This creates a map of MessageComponentTypes to their respective `InteractionCollectorOptionsResolvable` variant.
|
||||||
|
type CollectorOptionsTypeResolver<U extends InteractionCollectorOptionsResolvable> = {
|
||||||
|
readonly [T in U['componentType']]: TaggedUnion<InteractionCollectorOptionsResolvable, 'componentType', T>;
|
||||||
|
};
|
||||||
|
|
||||||
|
// This basically says "Given a `InteractionCollectorOptionsResolvable` variant", I'll give the corresponding
|
||||||
|
// `InteractionCollector<T>` variant back.
|
||||||
|
type ConditionalInteractionCollectorType<T extends InteractionCollectorOptionsResolvable | undefined> =
|
||||||
|
T extends InteractionCollectorOptions<infer Item>
|
||||||
|
? InteractionCollector<Item>
|
||||||
|
: InteractionCollector<MessageComponentInteraction>;
|
||||||
|
|
||||||
|
// This maps each componentType key to each variant.
|
||||||
|
type MappedInteractionCollectorOptions = CollectorOptionsTypeResolver<InteractionCollectorOptionsResolvable>;
|
||||||
|
|
||||||
|
// Converts mapped types to complimentary collector types.
|
||||||
|
type InteractionCollectorReturnType<T extends MessageComponentType | MessageComponentTypes | undefined> = T extends
|
||||||
|
| MessageComponentType
|
||||||
|
| MessageComponentTypes
|
||||||
|
? ConditionalInteractionCollectorType<MappedInteractionCollectorOptions[T]>
|
||||||
|
: InteractionCollector<MessageComponentInteraction>;
|
||||||
|
|
||||||
|
type MessageCollectorOptionsParams<T> =
|
||||||
|
| ({ componentType?: T } & InteractionCollectorOptionsResolvable)
|
||||||
|
| InteractionCollectorOptions<MessageComponentInteraction>;
|
||||||
|
|
||||||
|
type AwaitMessageCollectorOptionsParams<T> =
|
||||||
|
| ({ componentType?: T } & Pick<InteractionCollectorOptionsResolvable, keyof AwaitMessageComponentOptions<any>>)
|
||||||
|
| AwaitMessageComponentOptions<MessageComponentInteraction>;
|
||||||
|
|
||||||
export class Message extends Base {
|
export class Message extends Base {
|
||||||
public constructor(client: Client, data: RawMessageData);
|
public constructor(client: Client, data: RawMessageData);
|
||||||
private _patch(data: RawPartialMessageData, partial: true): void;
|
private _patch(data: RawPartialMessageData, partial: true): void;
|
||||||
@@ -1150,14 +1190,14 @@ export class Message extends Base {
|
|||||||
public webhookId: Snowflake | null;
|
public webhookId: Snowflake | null;
|
||||||
public flags: Readonly<MessageFlags>;
|
public flags: Readonly<MessageFlags>;
|
||||||
public reference: MessageReference | null;
|
public reference: MessageReference | null;
|
||||||
public awaitMessageComponent<T extends MessageComponentInteraction = MessageComponentInteraction>(
|
public awaitMessageComponent<T extends MessageComponentType | MessageComponentTypes | undefined = undefined>(
|
||||||
options?: AwaitMessageComponentOptions<T>,
|
options?: AwaitMessageCollectorOptionsParams<T>,
|
||||||
): Promise<T>;
|
): Promise<InteractionCollectorReturnType<T>>;
|
||||||
public awaitReactions(options?: AwaitReactionsOptions): Promise<Collection<Snowflake | string, MessageReaction>>;
|
public awaitReactions(options?: AwaitReactionsOptions): Promise<Collection<Snowflake | string, MessageReaction>>;
|
||||||
public createReactionCollector(options?: ReactionCollectorOptions): ReactionCollector;
|
public createReactionCollector(options?: ReactionCollectorOptions): ReactionCollector;
|
||||||
public createMessageComponentCollector<T extends MessageComponentInteraction = MessageComponentInteraction>(
|
public createMessageComponentCollector<
|
||||||
options?: InteractionCollectorOptions<T>,
|
T extends MessageComponentType | MessageComponentTypes | undefined = undefined,
|
||||||
): InteractionCollector<T>;
|
>(options?: MessageCollectorOptionsParams<T>): InteractionCollectorReturnType<T>;
|
||||||
public delete(): Promise<Message>;
|
public delete(): Promise<Message>;
|
||||||
public edit(content: string | MessageEditOptions | MessagePayload): Promise<Message>;
|
public edit(content: string | MessageEditOptions | MessagePayload): Promise<Message>;
|
||||||
public equals(message: Message, rawData: unknown): boolean;
|
public equals(message: Message, rawData: unknown): boolean;
|
||||||
@@ -2711,18 +2751,17 @@ export interface TextBasedChannelFields extends PartialTextBasedChannelFields {
|
|||||||
readonly lastMessage: Message | null;
|
readonly lastMessage: Message | null;
|
||||||
lastPinTimestamp: number | null;
|
lastPinTimestamp: number | null;
|
||||||
readonly lastPinAt: Date | null;
|
readonly lastPinAt: Date | null;
|
||||||
awaitMessageComponent<T extends MessageComponentInteraction = MessageComponentInteraction>(
|
awaitMessageComponent<T extends MessageComponentType | MessageComponentTypes | undefined = undefined>(
|
||||||
options?: AwaitMessageComponentOptions<T>,
|
options?: AwaitMessageCollectorOptionsParams<T>,
|
||||||
): Promise<T>;
|
): Promise<InteractionCollectorReturnType<T>>;
|
||||||
awaitMessages(options?: AwaitMessagesOptions): Promise<Collection<Snowflake, Message>>;
|
awaitMessages(options?: AwaitMessagesOptions): Promise<Collection<Snowflake, Message>>;
|
||||||
bulkDelete(
|
bulkDelete(
|
||||||
messages: Collection<Snowflake, Message> | readonly MessageResolvable[] | number,
|
messages: Collection<Snowflake, Message> | readonly MessageResolvable[] | number,
|
||||||
filterOld?: boolean,
|
filterOld?: boolean,
|
||||||
): Promise<Collection<Snowflake, Message>>;
|
): Promise<Collection<Snowflake, Message>>;
|
||||||
createMessageComponentCollector<T extends MessageComponentInteraction = MessageComponentInteraction>(
|
createMessageComponentCollector<T extends MessageComponentType | MessageComponentTypes | undefined = undefined>(
|
||||||
options?: InteractionCollectorOptions<T>,
|
options?: MessageCollectorOptionsParams<T>,
|
||||||
): InteractionCollector<T>;
|
): InteractionCollectorReturnType<T>;
|
||||||
createMessageCollector(options?: MessageCollectorOptions): MessageCollector;
|
|
||||||
sendTyping(): Promise<void>;
|
sendTyping(): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3959,6 +3998,23 @@ export interface InteractionCollectorOptions<T extends Interaction> extends Coll
|
|||||||
message?: Message | APIMessage;
|
message?: Message | APIMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ButtonInteractionCollectorOptions extends InteractionCollectorOptions<ButtonInteraction> {
|
||||||
|
componentType: 'BUTTON' | MessageComponentTypes.BUTTON;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SelectMenuInteractionCollectorOptions extends InteractionCollectorOptions<SelectMenuInteraction> {
|
||||||
|
componentType: 'SELECT_MENU' | MessageComponentTypes.SELECT_MENU;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MessageInteractionCollectorOptions extends InteractionCollectorOptions<MessageComponentInteraction> {
|
||||||
|
componentType: 'ACTION_ROW' | MessageComponentTypes.ACTION_ROW;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type InteractionCollectorOptionsResolvable =
|
||||||
|
| MessageInteractionCollectorOptions
|
||||||
|
| SelectMenuInteractionCollectorOptions
|
||||||
|
| ButtonInteractionCollectorOptions;
|
||||||
|
|
||||||
export interface InteractionDeferReplyOptions {
|
export interface InteractionDeferReplyOptions {
|
||||||
ephemeral?: boolean;
|
ephemeral?: boolean;
|
||||||
fetchReply?: boolean;
|
fetchReply?: boolean;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
ApplicationCommandResolvable,
|
ApplicationCommandResolvable,
|
||||||
ApplicationCommandSubCommandData,
|
ApplicationCommandSubCommandData,
|
||||||
ApplicationCommandSubGroupData,
|
ApplicationCommandSubGroupData,
|
||||||
|
ButtonInteraction,
|
||||||
CacheFactory,
|
CacheFactory,
|
||||||
Caches,
|
Caches,
|
||||||
CategoryChannel,
|
CategoryChannel,
|
||||||
@@ -31,12 +32,14 @@ import {
|
|||||||
GuildResolvable,
|
GuildResolvable,
|
||||||
Intents,
|
Intents,
|
||||||
Interaction,
|
Interaction,
|
||||||
|
InteractionCollector,
|
||||||
LimitedCollection,
|
LimitedCollection,
|
||||||
Message,
|
Message,
|
||||||
MessageActionRow,
|
MessageActionRow,
|
||||||
MessageAttachment,
|
MessageAttachment,
|
||||||
MessageButton,
|
MessageButton,
|
||||||
MessageCollector,
|
MessageCollector,
|
||||||
|
MessageComponentInteraction,
|
||||||
MessageEmbed,
|
MessageEmbed,
|
||||||
MessageManager,
|
MessageManager,
|
||||||
MessageReaction,
|
MessageReaction,
|
||||||
@@ -49,6 +52,7 @@ import {
|
|||||||
ReactionCollector,
|
ReactionCollector,
|
||||||
Role,
|
Role,
|
||||||
RoleManager,
|
RoleManager,
|
||||||
|
SelectMenuInteraction,
|
||||||
Serialized,
|
Serialized,
|
||||||
ShardClientUtil,
|
ShardClientUtil,
|
||||||
ShardingManager,
|
ShardingManager,
|
||||||
@@ -469,7 +473,8 @@ client.on('messageReactionRemoveAll', async message => {
|
|||||||
// This is to check that stuff is the right type
|
// This is to check that stuff is the right type
|
||||||
declare const assertIsMessage: (m: Promise<Message>) => void;
|
declare const assertIsMessage: (m: Promise<Message>) => void;
|
||||||
|
|
||||||
client.on('messageCreate', ({ channel }) => {
|
client.on('messageCreate', message => {
|
||||||
|
const { channel } = message;
|
||||||
assertIsMessage(channel.send('string'));
|
assertIsMessage(channel.send('string'));
|
||||||
assertIsMessage(channel.send({}));
|
assertIsMessage(channel.send({}));
|
||||||
assertIsMessage(channel.send({ embeds: [] }));
|
assertIsMessage(channel.send({ embeds: [] }));
|
||||||
@@ -484,6 +489,31 @@ client.on('messageCreate', ({ channel }) => {
|
|||||||
channel.send();
|
channel.send();
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
channel.send({ another: 'property' });
|
channel.send({ another: 'property' });
|
||||||
|
|
||||||
|
// Check collector creations.
|
||||||
|
|
||||||
|
// Verify that buttons interactions are inferred.
|
||||||
|
const buttonCollector = message.createMessageComponentCollector({ componentType: 'BUTTON' });
|
||||||
|
assertType<Promise<InteractionCollector<ButtonInteraction>>>(
|
||||||
|
message.awaitMessageComponent({ componentType: 'BUTTON' }),
|
||||||
|
);
|
||||||
|
assertType<InteractionCollector<ButtonInteraction>>(buttonCollector);
|
||||||
|
|
||||||
|
// Verify that select menus interaction are inferred.
|
||||||
|
const selectMenuCollector = message.createMessageComponentCollector({ componentType: 'SELECT_MENU' });
|
||||||
|
assertType<Promise<InteractionCollector<SelectMenuInteraction>>>(
|
||||||
|
message.awaitMessageComponent({ componentType: 'SELECT_MENU' }),
|
||||||
|
);
|
||||||
|
assertType<InteractionCollector<SelectMenuInteraction>>(selectMenuCollector);
|
||||||
|
|
||||||
|
// Verify that message component interactions are default collected types.
|
||||||
|
const defaultCollector = message.createMessageComponentCollector();
|
||||||
|
assertType<Promise<InteractionCollector<MessageComponentInteraction>>>(message.awaitMessageComponent());
|
||||||
|
assertType<InteractionCollector<MessageComponentInteraction>>(defaultCollector);
|
||||||
|
|
||||||
|
// Verify that additional options don't affect default collector types.
|
||||||
|
const semiDefaultCollector = message.createMessageComponentCollector({ interactionType: 'APPLICATION_COMMAND' });
|
||||||
|
assertType<InteractionCollector<MessageComponentInteraction>>(semiDefaultCollector);
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on('interaction', async interaction => {
|
client.on('interaction', async interaction => {
|
||||||
|
|||||||
Reference in New Issue
Block a user