diff --git a/src/services/processor.ts b/src/services/processor.ts index ba58212..660fe99 100644 --- a/src/services/processor.ts +++ b/src/services/processor.ts @@ -1,7 +1,7 @@ import type { Client } from "./client"; import type { Context } from "../types/context"; import { HandlerType, Trait, type EventPayload } from "../types/common"; -import { CommandHandler, type Handler, type ArgsFromOptions, OptionTypeMap } from "../types/handler"; +import { CommandHandler, type Handler, type ArgsFromOptions, OptionConstructorMap } from "../types/handler"; import type { API } from "./api"; import { ApplicationCommandType, type ApplicationCommandOption, type ApplicationCommandOptionResult } from "../types/applicationCommand"; import type { Emitter } from "./bus"; @@ -89,7 +89,7 @@ export class Processor { validated[def.name] = choice.value; } else { // Otherwise just check the type - if (arg.value instanceof OptionTypeMap[def.type]) { + if (arg.value instanceof OptionConstructorMap[def.type]) { // TODO: Coerce the type if possible throw new Error(`Invalid type for ${def.name}: expected ${def.type}, got ${typeof arg}`); } else { diff --git a/src/types/handler.ts b/src/types/handler.ts index 221a684..a4012e9 100644 --- a/src/types/handler.ts +++ b/src/types/handler.ts @@ -2,7 +2,7 @@ import { ApplicationCommandOptionType, type ApplicationCommandOption } from "./a import { Trait, type EventPayload } from "./common"; import type { Context } from "./context"; -export const OptionTypeMap = { +export const OptionConstructorMap = { [ApplicationCommandOptionType.String]: String, [ApplicationCommandOptionType.Integer]: Number, [ApplicationCommandOptionType.Boolean]: Boolean, @@ -16,6 +16,20 @@ export const OptionTypeMap = { [ApplicationCommandOptionType.SubCommandGroup]: String, // Handled by `options` }; +export type OptionTypeMap = { + [ApplicationCommandOptionType.String]: string, + [ApplicationCommandOptionType.Integer]: number, + [ApplicationCommandOptionType.Boolean]: boolean, + [ApplicationCommandOptionType.Number]: number, + [ApplicationCommandOptionType.User]: string, // Could be a user ID or object depending on your use case + [ApplicationCommandOptionType.Channel]: string, // Could be a channel ID or object + [ApplicationCommandOptionType.Role]: string, // Could be a role ID or object + [ApplicationCommandOptionType.Mentionable]: string, // Could be a mentionable ID or object + [ApplicationCommandOptionType.Attachment]: string, // Could represent attachment IDs + [ApplicationCommandOptionType.SubCommand]: string, // Handled by `options` + [ApplicationCommandOptionType.SubCommandGroup]: string, // Handled by `options` +}; + // Recursive type to map ApplicationCommandOption to arguments export type ArgsFromOptions = { [Option in T[number] as Option['name']]: Option extends { options: readonly ApplicationCommandOption[] } @@ -24,10 +38,10 @@ export type ArgsFromOptions = { ? Option['required'] extends true // If required, keep as is; otherwise, make optional ? U : U | undefined - : Option['type'] extends keyof typeof OptionTypeMap + : Option['type'] extends keyof OptionTypeMap ? Option['required'] extends true // If required, keep as is; otherwise, make optional - ? typeof OptionTypeMap[Option['type']] - : typeof OptionTypeMap[Option['type']] | undefined + ? OptionTypeMap[Option['type']] + : OptionTypeMap[Option['type']] | undefined : Option['required'] extends true ? unknown : unknown | undefined;