Skip to main content

@SlashOption

A slash command can have multiple options (parameters)

query is an option in this image

Signature

SlashOption(options: SlashOptionOptions);

Declare an option

To declare an option you simply use the @SlashOption decorator before a method parameter

@Discord()
class Example {
@Slash({ description: "add" })
add(
@SlashOption({
description: "x value",
name: "x",
required: true,
type: ApplicationCommandOptionType.Number,
})
x: number,
@SlashOption({
description: "y value",
name: "y",
required: true,
type: ApplicationCommandOptionType.Number,
})
y: number,
interaction: CommandInteraction,
) {
interaction.reply(String(x + y));
}
}

Create option using discord.js builders

import {
SlashCommandBuilder,
SlashCommandMentionableOption,
User,
type CommandInteraction,
} from "discord.js";
import { Discord, Slash, SlashOption } from "discordx";

const cmd = new SlashCommandBuilder()
.setName("hello")
.setDescription("Say hello!");

const user_option = new SlashCommandMentionableOption()
.setName("user")
.setDescription("Mention user to say hello to.")
.setRequired(true);

@Discord()
export class Example {
@Slash(cmd)
async hello(
@SlashOption(user_option) user: User,
interaction: CommandInteraction,
): Promise<void> {
await interaction.reply(`:wave: ${user}`);
}
}

Transformer

Act as middleware for your parameters. Take a look at the following example to see how useful it is.

class Document {
constructor(
public input: string,
public interaction: ChatInputCommandInteraction,
) {
/*
empty constructor
*/
}

async save(): Promise<void> {
/*
your logic to save input into database
*/

await this.interaction.followUp(
`${this.interaction.user} saved \`${this.input}\` into database`,
);
}
}

function DocumentTransformer(
input: string,
interaction: ChatInputCommandInteraction,
): Document {
return new Document(input, interaction);
}

@Discord()
export class Example {
@Slash({ description: "Save input into database", name: "save-input" })
async withTransformer(
@SlashOption(
{
description: "input",
name: "input",
required: true,
type: ApplicationCommandOptionType.String,
},
DocumentTransformer,
)
doc: Document,
interaction: ChatInputCommandInteraction,
): Promise<void> {
await interaction.deferReply();
doc.save();
}
}

Autocomplete option

Autocomplete interactions allow your application to dynamically return option suggestions to a user as they type. - discord

Method - Resolver

When defining an autocomplete slash option, you can define a resolver for autocomplete inside @SlashOption to simplify things.

@SlashOption({
autocomplete: function (
interaction: AutocompleteInteraction
) {
interaction.respond([
{ name: "option a", value: "a" },
{ name: "option b", value: "b" },
]);
},
description: "autocomplete",
name: "autocomplete",
required: true,
type: ApplicationCommandOptionType.String,
})
input: string,

Method - Boolean

discordx will call your command handler with autocomplete interaction if you use boolean instead of resolver.

@SlashOption({
autocomplete: true,
description: "choice",
name: "choice",
required: true,
type: ApplicationCommandOptionType.String,
}) input: string,
interaction: CommandInteraction | AutocompleteInteraction

Example - All Methods

@Discord()
class Example {
myCustomText = "Hello discordx";

@Slash({ description: "autocomplete" })
autocomplete(
@SlashOption({
autocomplete: true,
description: "option-a",
name: "option-a",
required: true,
type: ApplicationCommandOptionType.String,
})
searchText: string,
@SlashOption({
autocomplete: function (
this: Example,
interaction: AutocompleteInteraction,
) {
// The normal function has this (keyword), therefore class reference is available
console.log(this.myCustomText);

// resolver for option b
interaction.respond([
{ name: "option c", value: "d" },
{ name: "option d", value: "c" },
]);
},
description: "option-b",
name: "option-b",
required: true,
type: ApplicationCommandOptionType.String,
})
searchText2: string,
@SlashOption({
autocomplete: (interaction: AutocompleteInteraction) => {
// This is not available for the arrow function, so there is no class reference
interaction.respond([
{ name: "option e", value: "e" },
{ name: "option f", value: "f" },
]);
},
description: "option-c",
name: "option-c",
required: true,
type: ApplicationCommandOptionType.String,
})
searchText3: string,
interaction: CommandInteraction | AutocompleteInteraction,
): void {
// If autocomplete is not handled above, it will be passed to handler (see option-a definition)
if (interaction.isAutocomplete()) {
const focusedOption = interaction.options.getFocused(true);
// resolver for option a
if (focusedOption.name === "option-a") {
interaction.respond([
{ name: "option a", value: "a" },
{ name: "option b", value: "b" },
]);
}
} else {
interaction.reply(`${searchText}-${searchText2}-${searchText3}`);
}
}
}

Manual typing

If you want to specify the type manually you can do it:

@Discord()
class Example {
@Slash({ description: "Get id", name: "get-id" })
getID(
@SlashOption({
description: "x",
name: "x",
required: true,
type: ApplicationCommandOptionType.Mentionable,
})
mentionable: GuildMember | User | Role,
interaction: CommandInteraction,
) {
interaction.reply(mentionable.id);
}
}

Autocompletion (Option's choices)

You can use the @SlashChoice decorator

Option order

You have to put required options before optional ones
Or you will get this error:

(node:64399) UnhandledPromiseRejectionWarning: DiscordAPIError: Invalid Form Body
options[1]: Required options must be placed before non-required options