Skip to content

Commit dea6840

Browse files
vladfranguQjuhJiralite
authored
fix: type guard for sendable text-based channels (#10482)
* 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]>
1 parent c13f18e commit dea6840

File tree

4 files changed

+46
-2
lines changed

4 files changed

+46
-2
lines changed

packages/discord.js/src/structures/BaseChannel.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,14 @@ class BaseChannel extends Base {
155155
return 'availableTags' in this;
156156
}
157157

158+
/**
159+
* Indicates whether this channel is sendable.
160+
* @returns {boolean}
161+
*/
162+
isSendable() {
163+
return 'send' in this;
164+
}
165+
158166
toJSON(...props) {
159167
return super.toJSON({ createdTimestamp: true }, ...props);
160168
}

packages/discord.js/src/util/Constants.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,24 @@ exports.GuildTextBasedChannelTypes = [
117117
* * {@link ChannelType.PrivateThread}
118118
* * {@link ChannelType.GuildVoice}
119119
* * {@link ChannelType.GuildStageVoice}
120+
* * {@link ChannelType.GroupDM}
120121
* @typedef {ChannelType[]} TextBasedChannelTypes
121122
*/
122-
exports.TextBasedChannelTypes = [...exports.GuildTextBasedChannelTypes, ChannelType.DM];
123+
exports.TextBasedChannelTypes = [...exports.GuildTextBasedChannelTypes, ChannelType.DM, ChannelType.GroupDM];
124+
125+
/**
126+
* The types of channels that are text-based and can have messages sent into. The available types are:
127+
* * {@link ChannelType.DM}
128+
* * {@link ChannelType.GuildText}
129+
* * {@link ChannelType.GuildAnnouncement}
130+
* * {@link ChannelType.AnnouncementThread}
131+
* * {@link ChannelType.PublicThread}
132+
* * {@link ChannelType.PrivateThread}
133+
* * {@link ChannelType.GuildVoice}
134+
* * {@link ChannelType.GuildStageVoice}
135+
* @typedef {ChannelType[]} SendableChannels
136+
*/
137+
exports.SendableChannels = [...exports.GuildTextBasedChannelTypes, ChannelType.DM];
123138

124139
/**
125140
* The types of channels that are threads. The available types are:

packages/discord.js/typings/index.d.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -975,6 +975,7 @@ export abstract class BaseChannel extends Base {
975975
public isDMBased(): this is PartialGroupDMChannel | DMChannel | PartialDMChannel;
976976
public isVoiceBased(): this is VoiceBasedChannel;
977977
public isThreadOnly(): this is ThreadOnlyChannel;
978+
public isSendable(): this is SendableChannels;
978979
public toString(): ChannelMention | UserMention;
979980
}
980981

@@ -3867,6 +3868,7 @@ export const Constants: {
38673868
SweeperKeys: SweeperKey[];
38683869
NonSystemMessageTypes: NonSystemMessageType[];
38693870
TextBasedChannelTypes: TextBasedChannelTypes[];
3871+
SendableChannels: SendableChannelTypes[];
38703872
GuildTextBasedChannelTypes: GuildTextBasedChannelTypes[];
38713873
ThreadChannelTypes: ThreadChannelType[];
38723874
VoiceBasedChannelTypes: VoiceBasedChannelTypes[];
@@ -6879,11 +6881,15 @@ export type Channel =
68796881

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

6884+
export type SendableChannels = Extract<Channel, { send: (...args: any[]) => any }>;
6885+
68826886
export type TextBasedChannels = TextBasedChannel;
68836887

68846888
export type TextBasedChannelTypes = TextBasedChannel['type'];
68856889

6886-
export type GuildTextBasedChannelTypes = Exclude<TextBasedChannelTypes, ChannelType.DM>;
6890+
export type GuildTextBasedChannelTypes = Exclude<TextBasedChannelTypes, ChannelType.DM | ChannelType.GroupDM>;
6891+
6892+
export type SendableChannelTypes = SendableChannels['type'];
68876893

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

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ import {
209209
ApplicationEmoji,
210210
ApplicationEmojiManager,
211211
StickerPack,
212+
SendableChannels,
212213
} from '.';
213214
import { expectAssignable, expectDeprecated, expectNotAssignable, expectNotType, expectType } from 'tsd';
214215
import type { ContextMenuCommandBuilder, SlashCommandBuilder } from '@discordjs/builders';
@@ -2593,3 +2594,17 @@ declare const poll: Poll;
25932594
expectType<Collection<Snowflake, StickerPack>>(await client.fetchStickerPacks());
25942595
expectType<Collection<Snowflake, StickerPack>>(await client.fetchStickerPacks({}));
25952596
expectType<StickerPack>(await client.fetchStickerPacks({ packId: snowflake }));
2597+
2598+
client.on('interactionCreate', interaction => {
2599+
if (!interaction.channel) {
2600+
return;
2601+
}
2602+
2603+
// @ts-expect-error
2604+
interaction.channel.send();
2605+
2606+
if (interaction.channel.isSendable()) {
2607+
expectType<SendableChannels>(interaction.channel);
2608+
interaction.channel.send({ embeds: [] });
2609+
}
2610+
});

0 commit comments

Comments
 (0)