Using Modules from within a Collection

I am using a Collection type to store modules

I set it up like this:


module type Command = {
  let data: SlashCommandBuilder.t
  let execute: Interaction.t => Js.Promise.t<Message.t>
} 

let commands: Collection.t<string, module(Command)> = Collection.make()

commands->Collection.set(
  Commands_Example.data->SlashCommandBuilder.getCommandName,
  module(Commands_Example),
)->ignore

let commandName = interaction->Interaction.getCommandName

let command = commands->Collection.get(commandName)
   switch command->Js.Nullable.toOption {
        | None => ()
        | Some(command) => command.execute(interaction)->ignore // Errors here: "The record field execute can't be found."
   }
// Commands_Example.res
open Discord

let data =
  SlashCommandBuilder.make()
  ->SlashCommandBuilder.setName("ping")
  ->SlashCommandBuilder.setDescription("Replies with Pong!")

let execute = (interaction: Interaction.t) => {
  interaction->Interaction.reply("Pong!")
}

How can I call the underlying execute function?

Edit: got around this with %raw. Wonder if there is a better way?

| Some(command) => %raw(`command.execute(interaction)`)

If command is a first-class module, then you need to unpack it into a normal module before you can access any of its contents.

module C = unpack(command)
C.execute(interaction)->ignore

It’s also possible to unpack it as part of the destructuring pattern:

| Some(module(C)) => C.execute(interaction)->ignore
4 Likes