all repos — kitten @ 84532fc0726e827829bfb3b608a7194c272dcdd1

make description optional in options for custom IDs
vi did:web:vt3e.cat
Fri, 12 Jun 2026 20:55:11 +0100
commit

84532fc0726e827829bfb3b608a7194c272dcdd1

parent

3818aab38d4822726c0de15a23bd61d371ed9559

3 files changed, 42 insertions(+), 21 deletions(-)

jump to
M pkgs/core/src/commands.tspkgs/core/src/commands.ts

@@ -4,7 +4,7 @@ CommandInteraction,

UserContextMenuCommandInteraction, MessageContextMenuCommandInteraction, } from "discord.js"; -import type { Option, InferOptions } from "./options"; +import type { CommandOption, InferOptions } from "./options"; export const INTEGRATION_TYPES = { GUILD_INSTALL: 0,

@@ -36,7 +36,7 @@ constructor(

public name: string, public config: { description: string; - options?: Record<string, Option<any, any>>; + options?: Record<string, CommandOption<any, any>>; run: Function; }, ) {}

@@ -50,7 +50,7 @@ public name: string,

public description: string, ) {} - subcommand<O extends Record<string, Option<any, any>>>( + subcommand<O extends Record<string, CommandOption<any, any>>>( name: string, config: { description: string;

@@ -81,7 +81,7 @@ contexts?: InteractionContextType[];

}, ) {} - subcommand<O extends Record<string, Option<any, any>>>( + subcommand<O extends Record<string, CommandOption<any, any>>>( name: string, config: { description: string;

@@ -114,7 +114,7 @@ constructor(

public name: string, public config: { description: string; - options?: Record<string, Option<any, any>>; + options?: Record<string, CommandOption<any, any>>; integrationTypes?: IntegrationType[]; contexts?: InteractionContextType[]; run: Function;

@@ -145,7 +145,7 @@ ): CommandBuilder<Ctx & NewCtx> {

return new CommandBuilder<Ctx & NewCtx>([...this.middlewares, mw]); } - command<O extends Record<string, Option<any, any>>>( + command<O extends Record<string, CommandOption<any, any>>>( name: string, config: { description: string;

@@ -204,7 +204,7 @@ runOrConfig:

| ((interaction: MessageContextMenuCommandInteraction, ctx: Ctx) => Promise<void> | void) | { integrationTypes?: IntegrationType[]; - contexts?: InteractionContextType[]; + contexts?: IntegrationType[]; run: ( interaction: MessageContextMenuCommandInteraction, ctx: Ctx,
M pkgs/core/src/kitten.tspkgs/core/src/kitten.ts

@@ -16,7 +16,7 @@ ApplicationCommandType,

} from "discord.js"; import { HaltExecution } from "./errors"; -import { type Option, type InferOptions, OPTION_TYPES } from "./options"; +import { type Option, type CommandOption, type InferOptions, OPTION_TYPES } from "./options"; import { KittenComponent, type KittenComponentInteraction } from "./components"; import { Command,

@@ -51,7 +51,7 @@ builder() {

return new CommandBuilder(); } - command<O extends Record<string, Option<any, any>>>( + command<O extends Record<string, CommandOption<any, any>>>( name: string, config: { description: string;

@@ -445,7 +445,7 @@ }

} private transformOptionsForDiscord( - options?: Record<string, Option<any, any>>, + options?: Record<string, CommandOption<any, any>>, ): APIApplicationCommandBasicOption[] { if (!options) return [];
M pkgs/core/src/options.tspkgs/core/src/options.ts

@@ -24,13 +24,17 @@ type OptionType = keyof typeof OPTION_TYPES;

export interface Option<T, Req extends boolean> { type: OptionType; - description: string; + description?: string; required: Req; autocomplete?: ( interaction: AutocompleteInteraction, value: T, ) => Promise<ApplicationCommandOptionChoiceData[]> | ApplicationCommandOptionChoiceData[]; __type?: T; +} + +export interface CommandOption<T, Req extends boolean> extends Option<T, Req> { + description: string; } export type InferOptions<O> = {

@@ -47,20 +51,37 @@ value: T,

) => Promise<ApplicationCommandOptionChoiceData[]> | ApplicationCommandOptionChoiceData[]; const createOption = <T>(type: OptionType) => { - return ((description: string, config?: any): Option<T, any> => ({ - type, - description, - required: config?.required ?? false, - autocomplete: config?.autocomplete, - })) as { - ( + return (( + descriptionOrConfig?: string | { required?: boolean; autocomplete?: AutocompleteFn<T> }, + config?: { required?: boolean; autocomplete?: AutocompleteFn<T> }, + ): Option<T, any> => { + const hasDescription = typeof descriptionOrConfig === "string"; + const description = hasDescription ? descriptionOrConfig : undefined; + const actualConfig = hasDescription ? config : descriptionOrConfig; + + return { + type, + description, + required: actualConfig?.required ?? false, + autocomplete: actualConfig?.autocomplete, + }; + }) as { + // w/ description for commands + <Req extends boolean>( description: string, - config: { required: true; autocomplete?: AutocompleteFn<T> }, - ): Option<T, true>; + config: { required: Req; autocomplete?: AutocompleteFn<T> }, + ): CommandOption<T, Req>; ( description: string, config?: { required?: false; autocomplete?: AutocompleteFn<T> }, - ): Option<T, false>; + ): CommandOption<T, false>; + + // w/out description for components + <Req extends boolean>(config: { + required: Req; + autocomplete?: AutocompleteFn<T>; + }): Option<T, Req>; + (config?: { required?: false; autocomplete?: AutocompleteFn<T> }): Option<T, false>; }; };