mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-17 03:53:29 +01:00
types: allow message cached props to be narrowed (#6838)
Co-authored-by: Almeida <almeidx@pm.me> Co-authored-by: Antonio Román <kyradiscord@gmail.com> Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
This commit is contained in:
@@ -889,6 +889,14 @@ class Message extends Base {
|
|||||||
return equal;
|
return equal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this message is from a guild.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
inGuild() {
|
||||||
|
return Boolean(this.guildId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When concatenated with a string, this automatically concatenates the message's content instead of the object.
|
* When concatenated with a string, this automatically concatenates the message's content instead of the object.
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
|
|||||||
72
typings/index.d.ts
vendored
72
typings/index.d.ts
vendored
@@ -270,7 +270,7 @@ export class BaseClient extends EventEmitter {
|
|||||||
|
|
||||||
export type GuildCacheMessage<Cached extends GuildCacheState> = CacheTypeReducer<
|
export type GuildCacheMessage<Cached extends GuildCacheState> = CacheTypeReducer<
|
||||||
Cached,
|
Cached,
|
||||||
Message,
|
GuildMessage<Cached> & Message,
|
||||||
APIMessage,
|
APIMessage,
|
||||||
Message | APIMessage,
|
Message | APIMessage,
|
||||||
Message | APIMessage
|
Message | APIMessage
|
||||||
@@ -315,10 +315,9 @@ export type CacheHelper<
|
|||||||
Cached extends GuildCacheState,
|
Cached extends GuildCacheState,
|
||||||
> = T extends InteractionResponsesResolvable ? InteractionResponses<Cached> & T : GuildInteraction<Cached> & T;
|
> = T extends InteractionResponsesResolvable ? InteractionResponses<Cached> & T : GuildInteraction<Cached> & T;
|
||||||
|
|
||||||
export type GuildCached<T extends Interaction> = CacheHelper<T, 'cached'>;
|
export type CachedInteraction<T extends Interaction = Interaction> = CacheHelper<T, 'cached'>;
|
||||||
export type GuildRaw<T extends Interaction> = CacheHelper<T, 'raw'>;
|
export type RawInteraction<T extends Interaction = Interaction> = CacheHelper<T, 'raw'>;
|
||||||
export type GuildPresent<T extends Interaction> = CacheHelper<T, 'present'>;
|
export type PresentInteraction<T extends Interaction = Interaction> = CacheHelper<T, 'present'>;
|
||||||
|
|
||||||
export abstract class BaseGuild extends Base {
|
export abstract class BaseGuild extends Base {
|
||||||
protected constructor(client: Client, data: RawBaseGuildData);
|
protected constructor(client: Client, data: RawBaseGuildData);
|
||||||
public readonly createdAt: Date;
|
public readonly createdAt: Date;
|
||||||
@@ -1242,8 +1241,8 @@ export type TaggedUnion<T, K extends keyof T, V extends T[K]> = T extends Record
|
|||||||
: never;
|
: never;
|
||||||
|
|
||||||
// This creates a map of MessageComponentTypes to their respective `InteractionCollectorOptionsResolvable` variant.
|
// This creates a map of MessageComponentTypes to their respective `InteractionCollectorOptionsResolvable` variant.
|
||||||
export type CollectorOptionsTypeResolver<U extends InteractionCollectorOptionsResolvable> = {
|
export type CollectorOptionsTypeResolver<U extends InteractionCollectorOptionsResolvable<Cached>, Cached = boolean> = {
|
||||||
readonly [T in U['componentType']]: TaggedUnion<InteractionCollectorOptionsResolvable, 'componentType', T>;
|
readonly [T in U['componentType']]: TaggedUnion<U, 'componentType', T>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This basically says "Given a `InteractionCollectorOptionsResolvable` variant", I'll give the corresponding
|
// This basically says "Given a `InteractionCollectorOptionsResolvable` variant", I'll give the corresponding
|
||||||
@@ -1254,18 +1253,23 @@ export type ConditionalInteractionCollectorType<T extends InteractionCollectorOp
|
|||||||
: InteractionCollector<MessageComponentInteraction>;
|
: InteractionCollector<MessageComponentInteraction>;
|
||||||
|
|
||||||
// This maps each componentType key to each variant.
|
// This maps each componentType key to each variant.
|
||||||
export type MappedInteractionCollectorOptions = CollectorOptionsTypeResolver<InteractionCollectorOptionsResolvable>;
|
export type MappedInteractionCollectorOptions<Cached = boolean> = CollectorOptionsTypeResolver<
|
||||||
|
InteractionCollectorOptionsResolvable<Cached>,
|
||||||
|
Cached
|
||||||
|
>;
|
||||||
|
|
||||||
// Converts mapped types to complimentary collector types.
|
// Converts mapped types to complimentary collector types.
|
||||||
export type InteractionCollectorReturnType<T extends MessageComponentType | MessageComponentTypes | undefined> =
|
export type InteractionCollectorReturnType<
|
||||||
T extends MessageComponentType | MessageComponentTypes
|
T extends MessageComponentType | MessageComponentTypes | undefined,
|
||||||
? ConditionalInteractionCollectorType<MappedInteractionCollectorOptions[T]>
|
Cached extends boolean = false,
|
||||||
: InteractionCollector<MessageComponentInteraction>;
|
> = T extends MessageComponentType | MessageComponentTypes
|
||||||
|
? ConditionalInteractionCollectorType<MappedInteractionCollectorOptions<Cached>[T]>
|
||||||
|
: InteractionCollector<MessageComponentInteraction>;
|
||||||
|
|
||||||
export type InteractionExtractor<T extends MessageComponentType | MessageComponentTypes | undefined> = T extends
|
export type InteractionExtractor<T extends MessageComponentType | MessageComponentTypes | undefined> = T extends
|
||||||
| MessageComponentType
|
| MessageComponentType
|
||||||
| MessageComponentTypes
|
| MessageComponentTypes
|
||||||
? MappedInteractionCollectorOptions[T] extends InteractionCollectorOptions<infer Item>
|
? MappedInteractionCollectorOptions<false>[T] extends InteractionCollectorOptions<infer Item>
|
||||||
? Item
|
? Item
|
||||||
: never
|
: never
|
||||||
: MessageComponentInteraction;
|
: MessageComponentInteraction;
|
||||||
@@ -1281,6 +1285,23 @@ export type AwaitMessageCollectorOptionsParams<T extends MessageComponentType |
|
|||||||
keyof AwaitMessageComponentOptions<any>
|
keyof AwaitMessageComponentOptions<any>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
export type GuildTextBasedChannel = Exclude<TextBasedChannels, PartialDMChannel | DMChannel>;
|
||||||
|
|
||||||
|
export type CachedMessage = GuildMessage<'cached'> & Message;
|
||||||
|
export interface GuildMessage<Cached extends GuildCacheState = GuildCacheState> {
|
||||||
|
awaitMessageComponent<
|
||||||
|
T extends MessageComponentType | MessageComponentTypes | undefined = MessageComponentTypes.ACTION_ROW,
|
||||||
|
>(
|
||||||
|
options?: AwaitMessageCollectorOptionsParams<T>,
|
||||||
|
): Promise<InteractionResponses<Cached> & InteractionExtractor<T>>;
|
||||||
|
|
||||||
|
createMessageComponentCollector<T extends MessageComponentType | MessageComponentTypes | undefined = undefined>(
|
||||||
|
options?: MessageCollectorOptionsParams<T>,
|
||||||
|
): InteractionCollectorReturnType<T, true>;
|
||||||
|
|
||||||
|
readonly channel: CacheTypeReducer<Cached, GuildTextBasedChannel>;
|
||||||
|
}
|
||||||
|
|
||||||
export class Message extends Base {
|
export class Message extends Base {
|
||||||
private constructor(client: Client, data: RawMessageData);
|
private constructor(client: Client, data: RawMessageData);
|
||||||
private _patch(data: RawPartialMessageData | RawMessageData): void;
|
private _patch(data: RawPartialMessageData | RawMessageData): void;
|
||||||
@@ -1350,6 +1371,7 @@ export class Message extends Base {
|
|||||||
public toJSON(): unknown;
|
public toJSON(): unknown;
|
||||||
public toString(): string;
|
public toString(): string;
|
||||||
public unpin(): Promise<Message>;
|
public unpin(): Promise<Message>;
|
||||||
|
public inGuild(): this is GuildMessage<'cached'> & this;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MessageActionRow extends BaseMessageComponent {
|
export class MessageActionRow extends BaseMessageComponent {
|
||||||
@@ -4247,23 +4269,31 @@ export interface InteractionCollectorOptions<T extends Interaction> extends Coll
|
|||||||
message?: Message | APIMessage;
|
message?: Message | APIMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ButtonInteractionCollectorOptions extends MessageComponentCollectorOptions<ButtonInteraction> {
|
export interface ButtonInteractionCollectorOptions<Cached = boolean>
|
||||||
|
extends MessageComponentCollectorOptions<
|
||||||
|
Cached extends true ? CachedInteraction<ButtonInteraction> : ButtonInteraction
|
||||||
|
> {
|
||||||
componentType: 'BUTTON' | MessageComponentTypes.BUTTON;
|
componentType: 'BUTTON' | MessageComponentTypes.BUTTON;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SelectMenuInteractionCollectorOptions extends MessageComponentCollectorOptions<SelectMenuInteraction> {
|
export interface SelectMenuInteractionCollectorOptions<Cached = boolean>
|
||||||
|
extends MessageComponentCollectorOptions<
|
||||||
|
Cached extends true ? CachedInteraction<SelectMenuInteraction> : SelectMenuInteraction
|
||||||
|
> {
|
||||||
componentType: 'SELECT_MENU' | MessageComponentTypes.SELECT_MENU;
|
componentType: 'SELECT_MENU' | MessageComponentTypes.SELECT_MENU;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MessageInteractionCollectorOptions
|
export interface MessageInteractionCollectorOptions<Cached = boolean>
|
||||||
extends MessageComponentCollectorOptions<MessageComponentInteraction> {
|
extends MessageComponentCollectorOptions<
|
||||||
|
Cached extends true ? CachedInteraction<MessageComponentInteraction> : MessageComponentInteraction
|
||||||
|
> {
|
||||||
componentType: 'ACTION_ROW' | MessageComponentTypes.ACTION_ROW;
|
componentType: 'ACTION_ROW' | MessageComponentTypes.ACTION_ROW;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type InteractionCollectorOptionsResolvable =
|
export type InteractionCollectorOptionsResolvable<Cached = boolean> =
|
||||||
| MessageInteractionCollectorOptions
|
| MessageInteractionCollectorOptions<Cached>
|
||||||
| SelectMenuInteractionCollectorOptions
|
| SelectMenuInteractionCollectorOptions<Cached>
|
||||||
| ButtonInteractionCollectorOptions;
|
| ButtonInteractionCollectorOptions<Cached>;
|
||||||
|
|
||||||
export interface InteractionDeferReplyOptions {
|
export interface InteractionDeferReplyOptions {
|
||||||
ephemeral?: boolean;
|
ephemeral?: boolean;
|
||||||
|
|||||||
@@ -33,15 +33,19 @@ import {
|
|||||||
DMChannel,
|
DMChannel,
|
||||||
Guild,
|
Guild,
|
||||||
GuildApplicationCommandManager,
|
GuildApplicationCommandManager,
|
||||||
GuildCached,
|
CachedInteraction,
|
||||||
GuildChannelManager,
|
GuildChannelManager,
|
||||||
GuildEmoji,
|
GuildEmoji,
|
||||||
GuildEmojiManager,
|
GuildEmojiManager,
|
||||||
GuildMember,
|
GuildMember,
|
||||||
|
GuildMessage,
|
||||||
GuildResolvable,
|
GuildResolvable,
|
||||||
|
GuildTextBasedChannel,
|
||||||
|
GuildTextChannelResolvable,
|
||||||
Intents,
|
Intents,
|
||||||
Interaction,
|
Interaction,
|
||||||
InteractionCollector,
|
InteractionCollector,
|
||||||
|
InteractionResponses,
|
||||||
LimitedCollection,
|
LimitedCollection,
|
||||||
Message,
|
Message,
|
||||||
MessageActionRow,
|
MessageActionRow,
|
||||||
@@ -73,6 +77,7 @@ import {
|
|||||||
Typing,
|
Typing,
|
||||||
User,
|
User,
|
||||||
VoiceChannel,
|
VoiceChannel,
|
||||||
|
CachedMessage,
|
||||||
} from '.';
|
} from '.';
|
||||||
import { ApplicationCommandOptionTypes } from './enums';
|
import { ApplicationCommandOptionTypes } from './enums';
|
||||||
|
|
||||||
@@ -492,6 +497,22 @@ client.on('messageCreate', async message => {
|
|||||||
assertIsMessage(channel.send({ embeds: [embed] }));
|
assertIsMessage(channel.send({ embeds: [embed] }));
|
||||||
assertIsMessage(channel.send({ embeds: [embed], files: [attachment] }));
|
assertIsMessage(channel.send({ embeds: [embed], files: [attachment] }));
|
||||||
|
|
||||||
|
if (message.inGuild()) {
|
||||||
|
assertType<CachedMessage>(message);
|
||||||
|
const component = await message.awaitMessageComponent({ componentType: 'BUTTON' });
|
||||||
|
assertType<InteractionResponses<'cached'>>(component);
|
||||||
|
assertType<Promise<CachedMessage>>(component.reply({ fetchReply: true }));
|
||||||
|
|
||||||
|
const buttonCollector = message.createMessageComponentCollector({ componentType: 'BUTTON' });
|
||||||
|
assertType<InteractionCollector<CachedInteraction<ButtonInteraction>>>(buttonCollector);
|
||||||
|
assertType<GuildTextBasedChannel>(message.channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertType<TextBasedChannels>(message.channel);
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
|
assertType<GuildTextBasedChannel>(message.channel);
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
channel.send();
|
channel.send();
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@@ -876,8 +897,8 @@ declare const booleanValue: boolean;
|
|||||||
if (interaction.inGuild()) assertType<Snowflake>(interaction.guildId);
|
if (interaction.inGuild()) assertType<Snowflake>(interaction.guildId);
|
||||||
|
|
||||||
client.on('interactionCreate', async interaction => {
|
client.on('interactionCreate', async interaction => {
|
||||||
const consumeCachedCommand = (_i: GuildCached<CommandInteraction>) => {};
|
const consumeCachedCommand = (_i: CachedInteraction<CommandInteraction>) => {};
|
||||||
const consumeCachedInteraction = (_i: GuildCached<Interaction>) => {};
|
const consumeCachedInteraction = (_i: CachedInteraction<Interaction>) => {};
|
||||||
|
|
||||||
if (interaction.inCachedGuild()) {
|
if (interaction.inCachedGuild()) {
|
||||||
assertType<GuildMember>(interaction.member);
|
assertType<GuildMember>(interaction.member);
|
||||||
@@ -969,6 +990,12 @@ client.on('interactionCreate', async interaction => {
|
|||||||
assertType<APIInteractionDataResolvedGuildMember | null>(interaction.options.getMember('test'));
|
assertType<APIInteractionDataResolvedGuildMember | null>(interaction.options.getMember('test'));
|
||||||
assertType<APIInteractionDataResolvedGuildMember>(interaction.options.getMember('test', true));
|
assertType<APIInteractionDataResolvedGuildMember>(interaction.options.getMember('test', true));
|
||||||
} else if (interaction.inCachedGuild()) {
|
} else if (interaction.inCachedGuild()) {
|
||||||
|
const msg = await interaction.reply({ fetchReply: true });
|
||||||
|
const btn = await msg.awaitMessageComponent({ componentType: 'BUTTON' });
|
||||||
|
|
||||||
|
assertType<Message>(msg);
|
||||||
|
assertType<CachedInteraction<ButtonInteraction>>(btn);
|
||||||
|
|
||||||
consumeCachedCommand(interaction);
|
consumeCachedCommand(interaction);
|
||||||
assertType<GuildMember>(interaction.options.getMember('test', true));
|
assertType<GuildMember>(interaction.options.getMember('test', true));
|
||||||
assertType<GuildMember | null>(interaction.options.getMember('test'));
|
assertType<GuildMember | null>(interaction.options.getMember('test'));
|
||||||
|
|||||||
Reference in New Issue
Block a user