From 74763ef3fb4a31563320c7cff19453773bdb38de Mon Sep 17 00:00:00 2001 From: cherryblossom000 <31467609+cherryblossom000@users.noreply.github.com> Date: Sat, 29 Aug 2020 20:08:04 +1000 Subject: [PATCH] types: don't allow any object in the first parameter if second parameter is not given in TextBasedChannel#send (#4736) --- typings/index.d.ts | 89 +++++++++++++++++++++++++--------------------- typings/index.ts | 27 +++++++++++++- 2 files changed, 75 insertions(+), 41 deletions(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index d3b84826e..b1d13952d 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -60,14 +60,26 @@ declare module 'discord.js' { public static create( target: MessageTarget, - content?: StringResolvable, - options?: MessageOptions | WebhookMessageOptions | MessageAdditions, + content: APIMessageContentResolvable, + options?: undefined, + extra?: MessageOptions | WebhookMessageOptions, + ): APIMessage; + public static create( + target: MessageTarget, + content: StringResolvable, + options: MessageOptions | WebhookMessageOptions | MessageAdditions, extra?: MessageOptions | WebhookMessageOptions, ): APIMessage; public static partitionMessageAdditions( items: readonly (MessageEmbed | MessageAttachment)[], ): [MessageEmbed[], MessageAttachment[]]; public static resolveFile(fileLike: BufferResolvable | Stream | FileOptions | MessageAttachment): Promise; + public static transformOptions( + content: APIMessageContentResolvable, + options?: undefined, + extra?: MessageOptions | WebhookMessageOptions, + isWebhook?: boolean, + ): MessageOptions | WebhookMessageOptions; public static transformOptions( content: StringResolvable, options: MessageOptions | WebhookMessageOptions | MessageAdditions, @@ -995,33 +1007,29 @@ declare module 'discord.js' { ): Promise>; public createReactionCollector(filter: CollectorFilter, options?: ReactionCollectorOptions): ReactionCollector; public delete(options?: { timeout?: number; reason?: string }): Promise; - public edit(content: StringResolvable, options?: MessageEditOptions | MessageEmbed): Promise; - public edit(options: MessageEditOptions | MessageEmbed | APIMessage): Promise; + public edit( + content: APIMessageContentResolvable | MessageEditOptions | MessageEmbed | APIMessage, + ): Promise; + public edit(content: StringResolvable, options: MessageEditOptions | MessageEmbed): Promise; public equals(message: Message, rawData: object): boolean; public fetchWebhook(): Promise; public fetch(force?: boolean): Promise; public pin(options?: { reason?: string }): Promise; public react(emoji: EmojiIdentifierResolvable): Promise; public reply( - content?: StringResolvable, - options?: MessageOptions | MessageAdditions | (MessageOptions & { split?: false }) | MessageAdditions, + content: APIMessageContentResolvable | (MessageOptions & { split?: false }) | MessageAdditions, + ): Promise; + public reply(options: MessageOptions & { split: true | SplitOptions }): Promise; + public reply(options: MessageOptions | APIMessage): Promise; + public reply( + content: StringResolvable, + options: (MessageOptions & { split?: false }) | MessageAdditions, ): Promise; public reply( - content?: StringResolvable, - options?: (MessageOptions & { split: true | SplitOptions }) | MessageAdditions, - ): Promise; - public reply( - options?: - | MessageOptions - | MessageAdditions - | APIMessage - | (MessageOptions & { split?: false }) - | MessageAdditions - | APIMessage, - ): Promise; - public reply( - options?: (MessageOptions & { split: true | SplitOptions }) | MessageAdditions | APIMessage, + content: StringResolvable, + options: MessageOptions & { split: true | SplitOptions }, ): Promise; + public reply(content: StringResolvable, options: MessageOptions): Promise; public suppressEmbeds(suppress?: boolean): Promise; public toJSON(): object; public toString(): string; @@ -2042,16 +2050,13 @@ declare module 'discord.js' { lastMessageID: Snowflake | null; readonly lastMessage: Message | null; send( - options: MessageOptions | (MessageOptions & { split?: false }) | MessageAdditions | APIMessage, + content: APIMessageContentResolvable | (MessageOptions & { split?: false }) | MessageAdditions, ): Promise; - send( - options: (MessageOptions & { split: true | SplitOptions; content: StringResolvable }) | APIMessage, - ): Promise; - send( - content: StringResolvable, - options?: MessageOptions | (MessageOptions & { split?: false }) | MessageAdditions, - ): Promise; - send(content: StringResolvable, options?: MessageOptions & { split: true | SplitOptions }): Promise; + send(options: MessageOptions & { split: true | SplitOptions }): Promise; + send(options: MessageOptions | APIMessage): Promise; + send(content: StringResolvable, options: (MessageOptions & { split?: false }) | MessageAdditions): Promise; + send(content: StringResolvable, options: MessageOptions & { split: true | SplitOptions }): Promise; + send(content: StringResolvable, options: MessageOptions): Promise; } interface TextBasedChannelFields extends PartialTextBasedChannelFields { @@ -2082,17 +2087,19 @@ declare module 'discord.js' { delete(reason?: string): Promise; edit(options: WebhookEditData): Promise; send( - content?: StringResolvable, - options?: (WebhookMessageOptions & { split?: false }) | MessageAdditions, + content: APIMessageContentResolvable | (WebhookMessageOptions & { split?: false }) | MessageAdditions, + ): Promise; + send(options: WebhookMessageOptions & { split: true | SplitOptions }): Promise; + send(options: WebhookMessageOptions | APIMessage): Promise; + send( + content: StringResolvable, + options: (WebhookMessageOptions & { split?: false }) | MessageAdditions, ): Promise; send( - content?: StringResolvable, - options?: (WebhookMessageOptions & { split: true | SplitOptions }) | MessageAdditions, - ): Promise; - send(options?: (WebhookMessageOptions & { split?: false }) | MessageAdditions | APIMessage): Promise; - send( - options?: (WebhookMessageOptions & { split: true | SplitOptions }) | MessageAdditions | APIMessage, + content: StringResolvable, + options: WebhookMessageOptions & { split: true | SplitOptions }, ): Promise; + send(content: StringResolvable, options: WebhookMessageOptions): Promise; sendSlackMessage(body: object): Promise; } @@ -2166,6 +2173,8 @@ declare module 'discord.js' { REACTION_BLOCKED: number; } + type APIMessageContentResolvable = string | number | boolean | bigint | symbol | readonly StringResolvable[]; + interface AuditLogChange { key: string; old?: any; @@ -2706,7 +2715,7 @@ declare module 'discord.js' { } interface MessageEditOptions { - content?: string; + content?: StringResolvable; embed?: MessageEmbed | MessageEmbedOptions | null; code?: string | boolean; flags?: BitFieldResolvable; @@ -2786,7 +2795,7 @@ declare module 'discord.js' { interface MessageOptions { tts?: boolean; nonce?: string; - content?: string; + content?: StringResolvable; embed?: MessageEmbed | MessageEmbedOptions; disableMentions?: 'none' | 'all' | 'everyone'; allowedMentions?: MessageMentionOptions; @@ -2806,7 +2815,7 @@ declare module 'discord.js' { type MessageResolvable = Message | Snowflake; - type MessageTarget = TextChannel | DMChannel | User | GuildMember | Webhook | WebhookClient; + type MessageTarget = TextChannel | NewsChannel | DMChannel | User | GuildMember | Webhook | WebhookClient; type MessageType = | 'DEFAULT' diff --git a/typings/index.ts b/typings/index.ts index 26708a4ca..db7abe7c6 100644 --- a/typings/index.ts +++ b/typings/index.ts @@ -1,6 +1,6 @@ /// -import { Client } from 'discord.js'; +import { Client, Message, MessageAttachment, MessageEmbed } from 'discord.js'; const client: Client = new Client(); @@ -25,4 +25,29 @@ client.on('messageReactionRemoveAll', async message => { console.log(`messageReactionRemoveAll - content: ${message.content}`); }); +// These are to check that stuff is the right type +declare const assertIsMessage: (m: Promise) => void; +declare const assertIsMessageArray: (m: Promise) => void; + +client.on('message', ({ channel }) => { + assertIsMessage(channel.send('string')); + assertIsMessage(channel.send({})); + assertIsMessage(channel.send({ embed: {} })); + assertIsMessage(channel.send({ another: 'property' }, {})); + + const attachment = new MessageAttachment('file.png'); + const embed = new MessageEmbed(); + assertIsMessage(channel.send(attachment)); + assertIsMessage(channel.send(embed)); + assertIsMessage(channel.send([attachment, embed])); + + assertIsMessageArray(channel.send(Symbol('another primitive'), { split: true })); + assertIsMessageArray(channel.send({ split: true })); + + // @ts-expect-error + channel.send(); + // @ts-expect-error + channel.send({ another: 'property' }); +}); + client.login('absolutely-valid-token');