Slash Subcommands

Slash Subcommands are a very powerful extension to regular Slash Commands where similar Subcommands can be grouped together, providing an interface to users to do multiple related actions under similar names.

Creating Slash Subcommands is where the Declarative Interface that Chooksie provides really shine. It allows you to easily compose multiple Subcommands together without being forced to write them in a single place.

These commands live in the subcommands directory, and use the defineSlashSubcommand Definition Function for type support.

For type support for Subcommands and Subcommand Groups, you can use the defineSubcommand and defineSubcommandGroup Definition Functions respectively.

TIP

For more advanced uses, visit the Setup Method guide.

Subcommands (Inlined)

import { defineOption, defineSlashSubcommand, defineSubcommand } from 'chooksie'
import type { CommandInteraction } from 'discord.js'

function setup() {
  const getNumbers = (interaction: CommandInteraction) => {
    const x = interaction.options.getNumber('x', true)
    const y = interaction.options.getNumber('y', true)
    return [x, y] as const
  }

  return { getNumbers }
}

const numbers = [
  defineOption({
    name: 'x',
    description: 'The first number.',
    type: 'NUMBER',
    required: true,
  }),
  defineOption({
    name: 'y',
    description: 'The second number.',
    type: 'NUMBER',
    required: true,
  }),
]

export default defineSlashSubcommand({
  name: 'math',
  description: 'Do math stuff.',
  options: [
    defineSubcommand({
      name: 'add',
      description: 'Add two numbers.',
      type: 'SUB_COMMAND',
      setup,
      async execute(ctx) {
        const [x, y] = this.getNumbers(ctx.interaction)
        await ctx.interaction.reply(`${x} + ${y} = ${x + y}`)
      },
      options: numbers,
    }),
    defineSubcommand({
      name: 'subtract',
      description: 'Subtracts two numbers.',
      type: 'SUB_COMMAND',
      setup,
      async execute(ctx) {
        const [x, y] = this.getNumbers(ctx.interaction)
        await ctx.interaction.reply(`${x} - ${y} = ${x - y}`)
      },
      options: numbers,
    }),
  ],
})
































 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


import { defineOption, defineSlashSubcommand, defineSubcommand } from 'chooksie'

function setup() {
  const getNumbers = interaction => {
    const x = interaction.options.getNumber('x', true)
    const y = interaction.options.getNumber('y', true)
    return [x, y]
  }

  return { getNumbers }
}

const numbers = [
  defineOption({
    name: 'x',
    description: 'The first number.',
    type: 'NUMBER',
    required: true,
  }),
  defineOption({
    name: 'y',
    description: 'The second number.',
    type: 'NUMBER',
    required: true,
  }),
]

export default defineSlashSubcommand({
  name: 'math',
  description: 'Do math stuff.',
  options: [
    defineSubcommand({
      name: 'add',
      description: 'Add two numbers.',
      type: 'SUB_COMMAND',
      setup,
      async execute(ctx) {
        const [x, y] = this.getNumbers(ctx.interaction)
        await ctx.interaction.reply(`${x} + ${y} = ${x + y}`)
      },
      options: numbers,
    }),
    defineSubcommand({
      name: 'subtract',
      description: 'Subtracts two numbers.',
      type: 'SUB_COMMAND',
      setup,
      async execute(ctx) {
        const [x, y] = this.getNumbers(ctx.interaction)
        await ctx.interaction.reply(`${x} - ${y} = ${x - y}`)
      },
      options: numbers,
    }),
  ],
})































 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


const { defineOption, defineSlashSubcommand, defineSubcommand } = require('chooksie')

function setup() {
  const getNumbers = interaction => {
    const x = interaction.options.getNumber('x', true)
    const y = interaction.options.getNumber('y', true)
    return [x, y]
  }

  return { getNumbers }
}

const numbers = [
  defineOption({
    name: 'x',
    description: 'The first number.',
    type: 'NUMBER',
    required: true,
  }),
  defineOption({
    name: 'y',
    description: 'The second number.',
    type: 'NUMBER',
    required: true,
  }),
]

export default defineSlashSubcommand({
  name: 'math',
  description: 'Do math stuff.',
  options: [
    defineSubcommand({
      name: 'add',
      description: 'Add two numbers.',
      type: 'SUB_COMMAND',
      setup,
      async execute(ctx) {
        const [x, y] = this.getNumbers(ctx.interaction)
        await ctx.interaction.reply(`${x} + ${y} = ${x + y}`)
      },
      options: numbers,
    }),
    defineSubcommand({
      name: 'subtract',
      description: 'Subtracts two numbers.',
      type: 'SUB_COMMAND',
      setup,
      async execute(ctx) {
        const [x, y] = this.getNumbers(ctx.interaction)
        await ctx.interaction.reply(`${x} - ${y} = ${x - y}`)
      },
      options: numbers,
    }),
  ],
})































 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


Subcommands (Composed)

import { defineOption, defineSlashSubcommand, defineSubcommand } from 'chooksie'
import type { CommandInteraction } from 'discord.js'

function setup() {
  const getNumbers = (interaction: CommandInteraction) => {
    const x = interaction.options.getNumber('x', true)
    const y = interaction.options.getNumber('y', true)
    return [x, y] as const
  }

  return { getNumbers }
}

const numbers = [
  defineOption({
    name: 'x',
    description: 'The first number.',
    type: 'NUMBER',
    required: true,
  }),
  defineOption({
    name: 'y',
    description: 'The second number.',
    type: 'NUMBER',
    required: true,
  }),
]

const addition = defineSubcommand({
  name: 'add',
  description: 'Add two numbers.',
  type: 'SUB_COMMAND',
  setup,
  async execute(ctx) {
    const [x, y] = this.getNumbers(ctx.interaction)
    await ctx.interaction.reply(`${x} + ${y} = ${x + y}`)
  },
  options: numbers,
})

const subtraction = defineSubcommand({
  name: 'subtract',
  description: 'Subtracts two numbers.',
  type: 'SUB_COMMAND',
  setup,
  async execute(ctx) {
    const [x, y] = this.getNumbers(ctx.interaction)
    await ctx.interaction.reply(`${x} - ${y} = ${x - y}`)
  },
  options: numbers,
})

export default defineSlashSubcommand({
  name: 'math',
  description: 'Do math stuff.',
  options: [
    addition,
    subtraction,
  ],
})




























 
 
 
 
 
 
 
 
 
 
 

 
 
 
 
 
 
 
 
 
 
 





 
 


import { defineOption, defineSlashSubcommand, defineSubcommand } from 'chooksie'

function setup() {
  const getNumbers = interaction => {
    const x = interaction.options.getNumber('x', true)
    const y = interaction.options.getNumber('y', true)
    return [x, y]
  }

  return { getNumbers }
}

const numbers = [
  defineOption({
    name: 'x',
    description: 'The first number.',
    type: 'NUMBER',
    required: true,
  }),
  defineOption({
    name: 'y',
    description: 'The second number.',
    type: 'NUMBER',
    required: true,
  }),
]

const addition = defineSubcommand({
  name: 'add',
  description: 'Add two numbers.',
  type: 'SUB_COMMAND',
  setup,
  async execute(ctx) {
    const [x, y] = this.getNumbers(ctx.interaction)
    await ctx.interaction.reply(`${x} + ${y} = ${x + y}`)
  },
  options: numbers,
})

const subtraction = defineSubcommand({
  name: 'subtract',
  description: 'Subtracts two numbers.',
  type: 'SUB_COMMAND',
  setup,
  async execute(ctx) {
    const [x, y] = this.getNumbers(ctx.interaction)
    await ctx.interaction.reply(`${x} - ${y} = ${x - y}`)
  },
  options: numbers,
})

export default defineSlashSubcommand({
  name: 'math',
  description: 'Do math stuff.',
  options: [
    addition,
    subtraction,
  ],
})



























 
 
 
 
 
 
 
 
 
 
 

 
 
 
 
 
 
 
 
 
 
 





 
 


const { defineOption, defineSlashSubcommand, defineSubcommand } = require('chooksie')

function setup() {
  const getNumbers = interaction => {
    const x = interaction.options.getNumber('x', true)
    const y = interaction.options.getNumber('y', true)
    return [x, y]
  }

  return { getNumbers }
}

const numbers = [
  defineOption({
    name: 'x',
    description: 'The first number.',
    type: 'NUMBER',
    required: true,
  }),
  defineOption({
    name: 'y',
    description: 'The second number.',
    type: 'NUMBER',
    required: true,
  }),
]

const addition = defineSubcommand({
  name: 'add',
  description: 'Add two numbers.',
  type: 'SUB_COMMAND',
  setup,
  async execute(ctx) {
    const [x, y] = this.getNumbers(ctx.interaction)
    await ctx.interaction.reply(`${x} + ${y} = ${x + y}`)
  },
  options: numbers,
})

const subtraction = defineSubcommand({
  name: 'subtract',
  description: 'Subtracts two numbers.',
  type: 'SUB_COMMAND',
  setup,
  async execute(ctx) {
    const [x, y] = this.getNumbers(ctx.interaction)
    await ctx.interaction.reply(`${x} - ${y} = ${x - y}`)
  },
  options: numbers,
})

module.exports = defineSlashSubcommand({
  name: 'math',
  description: 'Do math stuff.',
  options: [
    addition,
    subtraction,
  ],
})



























 
 
 
 
 
 
 
 
 
 
 

 
 
 
 
 
 
 
 
 
 
 





 
 


Subcommand Groups (Inlined)

import { defineOption, defineSlashSubcommand, defineSubcommand, defineSubcommandGroup } from 'chooksie'

const stringOption = defineOption({
  name: 'text',
  description: 'The text to transform.',
  type: 'STRING',
  required: true,
})

export default defineSlashSubcommand({
  name: 'string',
  description: 'Perform string manipulations.',
  options: [
    defineSubcommandGroup({
      name: 'case',
      description: 'Change a string\'s case.',
      type: 'SUB_COMMAND_GROUP',
      options: [
        defineSubcommand({
          name: 'upper',
          description: 'Transform a text to be all uppercase.',
          type: 'SUB_COMMAND',
          async execute(ctx) {
            const targetText = ctx.interaction.options.getString('text', true)
            await ctx.interaction.reply(targetText.toUpperCase())
          },
          options: [stringOption],
        }),
        defineSubcommand({
          name: 'lower',
          description: 'Transform a text to be all lowercase.',
          type: 'SUB_COMMAND',
          async execute(ctx) {
            const targetText = ctx.interaction.options.getString('text', true)
            await ctx.interaction.reply(targetText.toLowerCase())
          },
          options: [stringOption],
        }),
      ],
    }),
  ],
})













 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 




import { defineOption, defineSlashSubcommand, defineSubcommand, defineSubcommandGroup } from 'chooksie'

const stringOption = defineOption({
  name: 'text',
  description: 'The text to transform.',
  type: 'STRING',
  required: true,
})

export default defineSlashSubcommand({
  name: 'string',
  description: 'Perform string manipulations.',
  options: [
    defineSubcommandGroup({
      name: 'case',
      description: 'Change a string\'s case.',
      type: 'SUB_COMMAND_GROUP',
      options: [
        defineSubcommand({
          name: 'upper',
          description: 'Transform a text to be all uppercase.',
          type: 'SUB_COMMAND',
          async execute(ctx) {
            const targetText = ctx.interaction.options.getString('text', true)
            await ctx.interaction.reply(targetText.toUpperCase())
          },
          options: [stringOption],
        }),
        defineSubcommand({
          name: 'lower',
          description: 'Transform a text to be all lowercase.',
          type: 'SUB_COMMAND',
          async execute(ctx) {
            const targetText = ctx.interaction.options.getString('text', true)
            await ctx.interaction.reply(targetText.toLowerCase())
          },
          options: [stringOption],
        }),
      ],
    }),
  ],
})













 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 




const { defineOption, defineSlashSubcommand, defineSubcommand, defineSubcommandGroup } = require('chooksie')

const stringOption = defineOption({
  name: 'text',
  description: 'The text to transform.',
  type: 'STRING',
  required: true,
})

module.exports = defineSlashSubcommand({
  name: 'string',
  description: 'Perform string manipulations.',
  options: [
    defineSubcommandGroup({
      name: 'case',
      description: 'Change a string\'s case.',
      type: 'SUB_COMMAND_GROUP',
      options: [
        defineSubcommand({
          name: 'upper',
          description: 'Transform a text to be all uppercase.',
          type: 'SUB_COMMAND',
          async execute(ctx) {
            const targetText = ctx.interaction.options.getString('text', true)
            await ctx.interaction.reply(targetText.toUpperCase())
          },
          options: [stringOption],
        }),
        defineSubcommand({
          name: 'lower',
          description: 'Transform a text to be all lowercase.',
          type: 'SUB_COMMAND',
          async execute(ctx) {
            const targetText = ctx.interaction.options.getString('text', true)
            await ctx.interaction.reply(targetText.toLowerCase())
          },
          options: [stringOption],
        }),
      ],
    }),
  ],
})













 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 




Subcommand Groups (Composed)

import { defineOption, defineSlashSubcommand, defineSubcommand, defineSubcommandGroup } from 'chooksie'

const stringOption = defineOption({
  name: 'text',
  description: 'The text to transform.',
  type: 'STRING',
  required: true,
})

const upper = defineSubcommand({
  name: 'upper',
  description: 'Transform a text to be all uppercase.',
  type: 'SUB_COMMAND',
  async execute(ctx) {
    const targetText = ctx.interaction.options.getString('text', true)
    await ctx.interaction.reply(targetText.toUpperCase())
  },
  options: [stringOption],
})

const lower = defineSubcommand({
  name: 'lower',
  description: 'Transform a text to be all lowercase.',
  type: 'SUB_COMMAND',
  async execute(ctx) {
    const targetText = ctx.interaction.options.getString('text', true)
    await ctx.interaction.reply(targetText.toLowerCase())
  },
  options: [stringOption],
})

const changeCase = defineSubcommandGroup({
  name: 'case',
  description: 'Change a string\'s case.',
  type: 'SUB_COMMAND_GROUP',
  options: [
    upper,
    lower,
  ],
})

export default defineSlashSubcommand({
  name: 'string',
  description: 'Perform string manipulations.',
  options: [changeCase],
})









 
 
 
 
 
 
 
 
 
 

 
 
 
 
 
 
 
 
 
 

 
 
 
 
 
 
 
 
 




 

import { defineOption, defineSlashSubcommand, defineSubcommand, defineSubcommandGroup } from 'chooksie'

const stringOption = defineOption({
  name: 'text',
  description: 'The text to transform.',
  type: 'STRING',
  required: true,
})

const upper = defineSubcommand({
  name: 'upper',
  description: 'Transform a text to be all uppercase.',
  type: 'SUB_COMMAND',
  async execute(ctx) {
    const targetText = ctx.interaction.options.getString('text', true)
    await ctx.interaction.reply(targetText.toUpperCase())
  },
  options: [stringOption],
})

const lower = defineSubcommand({
  name: 'lower',
  description: 'Transform a text to be all lowercase.',
  type: 'SUB_COMMAND',
  async execute(ctx) {
    const targetText = ctx.interaction.options.getString('text', true)
    await ctx.interaction.reply(targetText.toLowerCase())
  },
  options: [stringOption],
})

const changeCase = defineSubcommandGroup({
  name: 'case',
  description: 'Change a string\'s case.',
  type: 'SUB_COMMAND_GROUP',
  options: [
    upper,
    lower,
  ],
})

export default defineSlashSubcommand({
  name: 'string',
  description: 'Perform string manipulations.',
  options: [changeCase],
})









 
 
 
 
 
 
 
 
 
 

 
 
 
 
 
 
 
 
 
 

 
 
 
 
 
 
 
 
 




 

const { defineOption, defineSlashSubcommand, defineSubcommand, defineSubcommandGroup } = require('chooksie')

const stringOption = defineOption({
  name: 'text',
  description: 'The text to transform.',
  type: 'STRING',
  required: true,
})

const upper = defineSubcommand({
  name: 'upper',
  description: 'Transform a text to be all uppercase.',
  type: 'SUB_COMMAND',
  async execute(ctx) {
    const targetText = ctx.interaction.options.getString('text', true)
    await ctx.interaction.reply(targetText.toUpperCase())
  },
  options: [stringOption],
})

const lower = defineSubcommand({
  name: 'lower',
  description: 'Transform a text to be all lowercase.',
  type: 'SUB_COMMAND',
  async execute(ctx) {
    const targetText = ctx.interaction.options.getString('text', true)
    await ctx.interaction.reply(targetText.toLowerCase())
  },
  options: [stringOption],
})

const changeCase = defineSubcommandGroup({
  name: 'case',
  description: 'Change a string\'s case.',
  type: 'SUB_COMMAND_GROUP',
  options: [
    upper,
    lower,
  ],
})

module.exports = defineSlashSubcommand({
  name: 'string',
  description: 'Perform string manipulations.',
  options: [changeCase],
})