mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-18 20:43:30 +01:00
types(Interaction): allow Interaction cached properties to be type narrowed (#6668)
Co-authored-by: Sugden <28943913+NotSugden@users.noreply.github.com> Co-authored-by: Rodry <38259440+ImRodry@users.noreply.github.com> Co-authored-by: Antonio Román <kyradiscord@gmail.com>
This commit is contained in:
@@ -120,6 +120,22 @@ class Interaction extends Base {
|
|||||||
return Boolean(this.guildId && this.member);
|
return Boolean(this.guildId && this.member);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether or not this interaction is both cached and received from a guild.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
inCachedGuild() {
|
||||||
|
return Boolean(this.guild && this.member);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether or not this interaction is received from an uncached guild.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
inRawGuild() {
|
||||||
|
return Boolean(this.guildId && !this.guild && this.member);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether this interaction is a {@link CommandInteraction}.
|
* Indicates whether this interaction is a {@link CommandInteraction}.
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
"member-access": true,
|
"member-access": true,
|
||||||
"no-unnecessary-class": false,
|
"no-unnecessary-class": false,
|
||||||
"array-type": [true, "array"],
|
"array-type": [true, "array"],
|
||||||
|
"one-line": false,
|
||||||
"no-any-union": false,
|
"no-any-union": false,
|
||||||
"void-return": false
|
"void-return": false
|
||||||
}
|
}
|
||||||
|
|||||||
69
typings/index.d.ts
vendored
69
typings/index.d.ts
vendored
@@ -267,6 +267,22 @@ export class BaseClient extends EventEmitter {
|
|||||||
public toJSON(...props: Record<string, boolean | string>[]): unknown;
|
public toJSON(...props: Record<string, boolean | string>[]): unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type GuildCacheMessage<Cached extends GuildCacheState> = CacheTypeReducer<
|
||||||
|
Cached,
|
||||||
|
Message,
|
||||||
|
APIMessage,
|
||||||
|
Message | APIMessage,
|
||||||
|
Message | APIMessage
|
||||||
|
>;
|
||||||
|
|
||||||
|
export interface BaseGuildCommandInteraction<Cached extends GuildCacheState = GuildCacheState>
|
||||||
|
extends GuildInteraction<Cached> {
|
||||||
|
deferReply(options: InteractionDeferReplyOptions & { fetchReply: true }): Promise<GuildCacheMessage<Cached>>;
|
||||||
|
editReply(options: string | MessagePayload | WebhookEditMessageOptions): Promise<GuildCacheMessage<Cached>>;
|
||||||
|
fetchReply(): Promise<GuildCacheMessage<Cached>>;
|
||||||
|
reply(options: InteractionReplyOptions & { fetchReply: true }): Promise<GuildCacheMessage<Cached>>;
|
||||||
|
}
|
||||||
|
|
||||||
export abstract class BaseCommandInteraction extends Interaction {
|
export abstract class BaseCommandInteraction extends Interaction {
|
||||||
public readonly command: ApplicationCommand | ApplicationCommand<{ guild: GuildResolvable }> | null;
|
public readonly command: ApplicationCommand | ApplicationCommand<{ guild: GuildResolvable }> | null;
|
||||||
public readonly channel: TextBasedChannels | null;
|
public readonly channel: TextBasedChannels | null;
|
||||||
@@ -277,6 +293,9 @@ export abstract class BaseCommandInteraction extends Interaction {
|
|||||||
public ephemeral: boolean | null;
|
public ephemeral: boolean | null;
|
||||||
public replied: boolean;
|
public replied: boolean;
|
||||||
public webhook: InteractionWebhook;
|
public webhook: InteractionWebhook;
|
||||||
|
public inGuild(): this is BaseGuildCommandInteraction<'present'> & this;
|
||||||
|
public inCachedGuild(): this is BaseGuildCommandInteraction<'cached'> & this;
|
||||||
|
public inRawGuild(): this is BaseGuildCommandInteraction<'raw'> & this;
|
||||||
public deferReply(options: InteractionDeferReplyOptions & { fetchReply: true }): Promise<Message | APIMessage>;
|
public deferReply(options: InteractionDeferReplyOptions & { fetchReply: true }): Promise<Message | APIMessage>;
|
||||||
public deferReply(options?: InteractionDeferReplyOptions): Promise<void>;
|
public deferReply(options?: InteractionDeferReplyOptions): Promise<void>;
|
||||||
public deleteReply(): Promise<void>;
|
public deleteReply(): Promise<void>;
|
||||||
@@ -579,7 +598,10 @@ export abstract class Collector<K, V, F extends unknown[] = []> extends EventEmi
|
|||||||
public once(event: 'end', listener: (collected: Collection<K, V>, reason: string) => Awaitable<void>): this;
|
public once(event: 'end', listener: (collected: Collection<K, V>, reason: string) => Awaitable<void>): this;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CommandInteraction extends BaseCommandInteraction {
|
export type GuildCommandInteraction<Cached extends GuildCacheState = GuildCacheState> =
|
||||||
|
BaseGuildCommandInteraction<Cached> & CommandInteraction;
|
||||||
|
|
||||||
|
export class CommandInteraction extends BaseCommandInteraction implements GuildCachedInteraction<CommandInteraction> {
|
||||||
public options: CommandInteractionOptionResolver;
|
public options: CommandInteractionOptionResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,7 +661,19 @@ export class CommandInteractionOptionResolver {
|
|||||||
public getMessage(name: string, required?: boolean): NonNullable<CommandInteractionOption['message']> | null;
|
public getMessage(name: string, required?: boolean): NonNullable<CommandInteractionOption['message']> | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ContextMenuInteraction extends BaseCommandInteraction {
|
export type GuildContextMenuInteraction<Cached extends GuildCacheState = GuildCacheState> =
|
||||||
|
BaseGuildCommandInteraction<Cached> & ContextMenuInteraction;
|
||||||
|
|
||||||
|
export interface GuildCachedInteraction<T> {
|
||||||
|
inGuild(): this is BaseGuildCommandInteraction<'present'> & T;
|
||||||
|
inCachedGuild(): this is BaseGuildCommandInteraction<'cached'> & T;
|
||||||
|
inRawGuild(): this is BaseGuildCommandInteraction<'raw'> & T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ContextMenuInteraction
|
||||||
|
extends BaseCommandInteraction
|
||||||
|
implements GuildCachedInteraction<ContextMenuInteraction>
|
||||||
|
{
|
||||||
public options: CommandInteractionOptionResolver;
|
public options: CommandInteractionOptionResolver;
|
||||||
public targetId: Snowflake;
|
public targetId: Snowflake;
|
||||||
public targetType: Exclude<ApplicationCommandType, 'CHAT_INPUT'>;
|
public targetType: Exclude<ApplicationCommandType, 'CHAT_INPUT'>;
|
||||||
@@ -1042,6 +1076,29 @@ export class Intents extends BitField<IntentsString> {
|
|||||||
public static resolve(bit?: BitFieldResolvable<IntentsString, number>): number;
|
public static resolve(bit?: BitFieldResolvable<IntentsString, number>): number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type GuildCacheState = 'cached' | 'raw' | 'present';
|
||||||
|
|
||||||
|
type CacheTypeReducer<
|
||||||
|
State extends GuildCacheState,
|
||||||
|
CachedType,
|
||||||
|
RawType = CachedType,
|
||||||
|
PresentType = CachedType | RawType,
|
||||||
|
Fallback = PresentType | null,
|
||||||
|
> = State extends 'cached'
|
||||||
|
? CachedType
|
||||||
|
: State extends 'raw'
|
||||||
|
? RawType
|
||||||
|
: State extends 'present'
|
||||||
|
? PresentType
|
||||||
|
: Fallback;
|
||||||
|
|
||||||
|
export interface GuildInteraction<Cached extends GuildCacheState = GuildCacheState> extends Interaction {
|
||||||
|
guildId: Snowflake;
|
||||||
|
member: CacheTypeReducer<Cached, GuildMember, APIInteractionGuildMember>;
|
||||||
|
readonly guild: CacheTypeReducer<Cached, Guild, null>;
|
||||||
|
channel: CacheTypeReducer<Cached, Exclude<TextBasedChannels, PartialDMChannel | DMChannel> | null>;
|
||||||
|
}
|
||||||
|
|
||||||
export class Interaction extends Base {
|
export class Interaction extends Base {
|
||||||
protected constructor(client: Client, data: RawInteractionData);
|
protected constructor(client: Client, data: RawInteractionData);
|
||||||
public applicationId: Snowflake;
|
public applicationId: Snowflake;
|
||||||
@@ -1058,11 +1115,9 @@ export class Interaction extends Base {
|
|||||||
public user: User;
|
public user: User;
|
||||||
public version: number;
|
public version: number;
|
||||||
public memberPermissions: Readonly<Permissions> | null;
|
public memberPermissions: Readonly<Permissions> | null;
|
||||||
public inGuild(): this is this & {
|
public inGuild(): this is GuildInteraction<'present'> & this;
|
||||||
guildId: Snowflake;
|
public inCachedGuild(): this is GuildInteraction<'cached'> & this;
|
||||||
member: GuildMember | APIInteractionGuildMember;
|
public inRawGuild(): this is GuildInteraction<'raw'> & this;
|
||||||
readonly channel: Exclude<TextBasedChannels, PartialDMChannel | DMChannel> | null;
|
|
||||||
};
|
|
||||||
public isButton(): this is ButtonInteraction;
|
public isButton(): this is ButtonInteraction;
|
||||||
public isCommand(): this is CommandInteraction;
|
public isCommand(): this is CommandInteraction;
|
||||||
public isContextMenu(): this is ContextMenuInteraction;
|
public isContextMenu(): this is ContextMenuInteraction;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { APIInteractionGuildMember } from 'discord-api-types';
|
import { APIGuildMember, APIInteractionGuildMember, APIMessage } from 'discord-api-types/v9';
|
||||||
import {
|
import {
|
||||||
ApplicationCommand,
|
ApplicationCommand,
|
||||||
ApplicationCommandChannelOption,
|
ApplicationCommandChannelOption,
|
||||||
@@ -25,6 +25,7 @@ import {
|
|||||||
CommandOptionChoiceResolvableType,
|
CommandOptionChoiceResolvableType,
|
||||||
CommandOptionNonChoiceResolvableType,
|
CommandOptionNonChoiceResolvableType,
|
||||||
Constants,
|
Constants,
|
||||||
|
ContextMenuInteraction,
|
||||||
DMChannel,
|
DMChannel,
|
||||||
Guild,
|
Guild,
|
||||||
GuildApplicationCommandManager,
|
GuildApplicationCommandManager,
|
||||||
@@ -856,7 +857,82 @@ 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 => {
|
||||||
|
if (interaction.inCachedGuild()) {
|
||||||
|
assertType<GuildMember>(interaction.member);
|
||||||
|
} else if (interaction.inRawGuild()) {
|
||||||
|
assertType<APIInteractionGuildMember>(interaction.member);
|
||||||
|
} else {
|
||||||
|
assertType<APIGuildMember | GuildMember | null>(interaction.member);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interaction.isContextMenu()) {
|
||||||
|
assertType<ContextMenuInteraction>(interaction);
|
||||||
|
if (interaction.inCachedGuild()) {
|
||||||
|
assertType<ContextMenuInteraction>(interaction);
|
||||||
|
assertType<Guild>(interaction.guild);
|
||||||
|
} else if (interaction.inRawGuild()) {
|
||||||
|
assertType<ContextMenuInteraction>(interaction);
|
||||||
|
assertType<null>(interaction.guild);
|
||||||
|
} else if (interaction.inGuild()) {
|
||||||
|
assertType<ContextMenuInteraction>(interaction);
|
||||||
|
assertType<Guild | null>(interaction.guild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interaction.isButton()) {
|
||||||
|
assertType<ButtonInteraction>(interaction);
|
||||||
|
if (interaction.inCachedGuild()) {
|
||||||
|
assertType<ButtonInteraction>(interaction);
|
||||||
|
assertType<Guild>(interaction.guild);
|
||||||
|
} else if (interaction.inRawGuild()) {
|
||||||
|
assertType<ButtonInteraction>(interaction);
|
||||||
|
assertType<null>(interaction.guild);
|
||||||
|
} else if (interaction.inGuild()) {
|
||||||
|
assertType<ButtonInteraction>(interaction);
|
||||||
|
assertType<Guild | null>(interaction.guild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interaction.isMessageComponent()) {
|
||||||
|
assertType<MessageComponentInteraction>(interaction);
|
||||||
|
if (interaction.inCachedGuild()) {
|
||||||
|
assertType<MessageComponentInteraction>(interaction);
|
||||||
|
assertType<Guild>(interaction.guild);
|
||||||
|
} else if (interaction.inRawGuild()) {
|
||||||
|
assertType<MessageComponentInteraction>(interaction);
|
||||||
|
assertType<null>(interaction.guild);
|
||||||
|
} else if (interaction.inGuild()) {
|
||||||
|
assertType<MessageComponentInteraction>(interaction);
|
||||||
|
assertType<Guild | null>(interaction.guild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interaction.isSelectMenu()) {
|
||||||
|
assertType<SelectMenuInteraction>(interaction);
|
||||||
|
if (interaction.inCachedGuild()) {
|
||||||
|
assertType<SelectMenuInteraction>(interaction);
|
||||||
|
assertType<Guild>(interaction.guild);
|
||||||
|
} else if (interaction.inRawGuild()) {
|
||||||
|
assertType<SelectMenuInteraction>(interaction);
|
||||||
|
assertType<null>(interaction.guild);
|
||||||
|
} else if (interaction.inGuild()) {
|
||||||
|
assertType<SelectMenuInteraction>(interaction);
|
||||||
|
assertType<Guild | null>(interaction.guild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (interaction.isCommand()) {
|
if (interaction.isCommand()) {
|
||||||
|
if (interaction.inRawGuild()) {
|
||||||
|
assertType<CommandInteraction>(interaction);
|
||||||
|
assertType<Promise<APIMessage>>(interaction.reply({ fetchReply: true }));
|
||||||
|
} else if (interaction.inCachedGuild()) {
|
||||||
|
assertType<CommandInteraction>(interaction);
|
||||||
|
assertType<Promise<Message>>(interaction.reply({ fetchReply: true }));
|
||||||
|
} else {
|
||||||
|
assertType<CommandInteraction>(interaction);
|
||||||
|
assertType<Promise<Message | APIMessage>>(interaction.reply({ fetchReply: true }));
|
||||||
|
}
|
||||||
|
|
||||||
assertType<CommandInteraction>(interaction);
|
assertType<CommandInteraction>(interaction);
|
||||||
assertType<CommandInteractionOptionResolver>(interaction.options);
|
assertType<CommandInteractionOptionResolver>(interaction.options);
|
||||||
assertType<readonly CommandInteractionOption[]>(interaction.options.data);
|
assertType<readonly CommandInteractionOption[]>(interaction.options.data);
|
||||||
|
|||||||
Reference in New Issue
Block a user