Skip to content

Commit

Permalink
fix: type guard for sendable text-based channels (#10482)
Browse files Browse the repository at this point in the history
* fix: type-guard for sendable text-based channels

* chore: suggested change

* Update packages/discord.js/typings/index.test-d.ts

Co-authored-by: Qjuh <[email protected]>

* fix: make isSendable strictly check for `.send`

* fix: tests

---------

Co-authored-by: Qjuh <[email protected]>
Co-authored-by: Jiralite <[email protected]>
  • Loading branch information
3 people committed Sep 6, 2024
1 parent c13f18e commit dea6840
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 2 deletions.
8 changes: 8 additions & 0 deletions packages/discord.js/src/structures/BaseChannel.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,14 @@ class BaseChannel extends Base {
return 'availableTags' in this;
}

/**
* Indicates whether this channel is sendable.
* @returns {boolean}
*/
isSendable() {
return 'send' in this;
}

toJSON(...props) {
return super.toJSON({ createdTimestamp: true }, ...props);
}
Expand Down
17 changes: 16 additions & 1 deletion packages/discord.js/src/util/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,24 @@ exports.GuildTextBasedChannelTypes = [
* * {@link ChannelType.PrivateThread}
* * {@link ChannelType.GuildVoice}
* * {@link ChannelType.GuildStageVoice}
* * {@link ChannelType.GroupDM}
* @typedef {ChannelType[]} TextBasedChannelTypes
*/
exports.TextBasedChannelTypes = [...exports.GuildTextBasedChannelTypes, ChannelType.DM];
exports.TextBasedChannelTypes = [...exports.GuildTextBasedChannelTypes, ChannelType.DM, ChannelType.GroupDM];

/**
* The types of channels that are text-based and can have messages sent into. The available types are:
* * {@link ChannelType.DM}
* * {@link ChannelType.GuildText}
* * {@link ChannelType.GuildAnnouncement}
* * {@link ChannelType.AnnouncementThread}
* * {@link ChannelType.PublicThread}
* * {@link ChannelType.PrivateThread}
* * {@link ChannelType.GuildVoice}
* * {@link ChannelType.GuildStageVoice}
* @typedef {ChannelType[]} SendableChannels
*/
exports.SendableChannels = [...exports.GuildTextBasedChannelTypes, ChannelType.DM];

/**
* The types of channels that are threads. The available types are:
Expand Down
8 changes: 7 additions & 1 deletion packages/discord.js/typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -975,6 +975,7 @@ export abstract class BaseChannel extends Base {
public isDMBased(): this is PartialGroupDMChannel | DMChannel | PartialDMChannel;
public isVoiceBased(): this is VoiceBasedChannel;
public isThreadOnly(): this is ThreadOnlyChannel;
public isSendable(): this is SendableChannels;
public toString(): ChannelMention | UserMention;
}

Expand Down Expand Up @@ -3867,6 +3868,7 @@ export const Constants: {
SweeperKeys: SweeperKey[];
NonSystemMessageTypes: NonSystemMessageType[];
TextBasedChannelTypes: TextBasedChannelTypes[];
SendableChannels: SendableChannelTypes[];
GuildTextBasedChannelTypes: GuildTextBasedChannelTypes[];
ThreadChannelTypes: ThreadChannelType[];
VoiceBasedChannelTypes: VoiceBasedChannelTypes[];
Expand Down Expand Up @@ -6879,11 +6881,15 @@ export type Channel =

export type TextBasedChannel = Exclude<Extract<Channel, { type: TextChannelType }>, ForumChannel | MediaChannel>;

export type SendableChannels = Extract<Channel, { send: (...args: any[]) => any }>;

export type TextBasedChannels = TextBasedChannel;

export type TextBasedChannelTypes = TextBasedChannel['type'];

export type GuildTextBasedChannelTypes = Exclude<TextBasedChannelTypes, ChannelType.DM>;
export type GuildTextBasedChannelTypes = Exclude<TextBasedChannelTypes, ChannelType.DM | ChannelType.GroupDM>;

export type SendableChannelTypes = SendableChannels['type'];

export type VoiceBasedChannel = Extract<Channel, { bitrate: number }>;

Expand Down
15 changes: 15 additions & 0 deletions packages/discord.js/typings/index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ import {
ApplicationEmoji,
ApplicationEmojiManager,
StickerPack,
SendableChannels,
} from '.';
import { expectAssignable, expectDeprecated, expectNotAssignable, expectNotType, expectType } from 'tsd';
import type { ContextMenuCommandBuilder, SlashCommandBuilder } from '@discordjs/builders';
Expand Down Expand Up @@ -2593,3 +2594,17 @@ declare const poll: Poll;
expectType<Collection<Snowflake, StickerPack>>(await client.fetchStickerPacks());
expectType<Collection<Snowflake, StickerPack>>(await client.fetchStickerPacks({}));
expectType<StickerPack>(await client.fetchStickerPacks({ packId: snowflake }));

client.on('interactionCreate', interaction => {
if (!interaction.channel) {
return;
}

// @ts-expect-error
interaction.channel.send();

if (interaction.channel.isSendable()) {
expectType<SendableChannels>(interaction.channel);
interaction.channel.send({ embeds: [] });
}
});

0 comments on commit dea6840

Please sign in to comment.