Skip to content

ApplicationCommand.equals() failing due to undefined values not matching default values #10920

Open
@faceboy1392

Description

@faceboy1392

Which package is this bug report for?

discord.js

Issue description

now maybe I'm just doing something wrong, but I don't think this behavior makes sense. This is the first time I've opened an issue, forgive me if idk what I'm doing

What I'm trying to do

I have a local ApplicationCommandData object, which I'll call localCommand, that I am using to define the structure of a command. I can either set this as an object literal following that type or a SlashCommandBuilder().toJSON() as ApplicationCommandData (these two have slightly different behavior that I'll get into later). Either way, I leave most of the properties of the command unset.

Previously, I have registered localCommand to discord, and on startup, my bot grabs that registered command, which I'll call registeredCommand. Between startups, I have changed nothing about localCommand. In theory, registeredCommand is exactly what I registered using ApplicationCommandManager.create(localCommand), so all the properties should approximately match.

On startup, it should check localCommand and registeredCommand, and if localCommand has been changed, it should notice that the two are not equal and then update registeredCommand to match localCommand.

Problem is, registeredCommand.equals(localCommand) always returns false, despite registeredCommand being the result of directly registering localCommand.

Why it isn't working, and workaround

When logging localCommand and registeredCommand:
localCommand.integration_types: undefined
registeredCommand.integrationTypes: [ 0, 1 ]

iirc [ 0, 1 ] is the default for integrationTypes, so I would expect not defining the integration types in localCommand to be treated as using the default value, but that doesn't seem to be the case.

In src/structures/ApplicationCommand.js line 448, part of ApplicationCommand.isEqual():

      !isEqual(command.integrationTypes ?? command.integration_types ?? [], this.integrationTypes ?? [])

if I'm not mistaken, command.integrationTypes ?? command.integration_types ?? [] collapses down to [] since it is undefined, meanwhile this.integrationTypes ?? [] becomes [0, 1] because that is the default value, and so those are not considered as equal.

If I specifically set registeredCommand.integrationTypes = [] before checking if the commands are equal, it fixes this problem.

another thing with default values

When using SlashCommandBuilder().toJSON() as ApplicationCommandData, it comes with a bunch of fields that are set to undefined. for some properties, ApplicationCommand.equals() just uses in to check if the property exists, and then checks for strict inequality.

for example, localCommand.nsfw = undefined (property explicitly set as undefined by the builder, so it passes the "nsfw" in command check), but registeredCommand.nsfw = false, since that is the default value, and false !== undefined so it fails that check.

I'm not sure if this is intended behavior or not, and I can work around it by completely deleteing properties that are set to undefined, but I would expect that it would treat undefined as being equal to the default value for that property.

Code sample

command.data.structure = new SlashCommandBuilder()
      .setName("reload")
      .setDescription("_")
      .addStringOption((o) => o.setName("command").setDescription("The command to reload").setRequired(true))
      .toJSON() as ApplicationCommandData;
// note that integration types are never set, but when this command is registered, they seem to default to [0,1]

const registeredCommand = this.client.application.commands.cache.get(regCmd.id);

const localCommand: ApplicationCommandData = command.data.structure as ApplicationCommandData;

// registeredCommand should roughly match localCommand. localCommand was previously registered, and registeredCommand is what discord returns when fetching that same command back

if (!registeredCommand.equals(localCommand, true)) {
  console.log("NUH UH"); // this does log NUH UH
}

Versions

discord.js 14.19.3

Issue priority

Low (slightly annoying)

Which partials do you have configured?

Not applicable

Which gateway intents are you subscribing to?

Not applicable

I have tested this issue on a development release

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions