You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在TypeScript中为Discord机器人兼容消息与交互命令的类型问题

问题解决方案

1. 拆分类型定义,避免联合类型模糊

先把不同类型的命令成员拆分,明确边界,让TypeScript能正确进行类型推断:

// 保留原有基础类型
type RunFunction = (message: Message, arg: string) => Awaitable<string | MessagePayload | MessageCreateOptions | void>;
type SimpleCommandResponse = string;

// 拆分支持交互的Command和普通Command
type InteractionSupportedCommand = {
  acceptsInteraction: true;
  run: (interactionOrMessage: CommandInteraction | Message, arguments?: string) => Awaitable<string | MessagePayload | MessageCreateOptions | void>;
};

type BasicCommand = {
  acceptsInteraction?: false;
  run: RunFunction;
};

// 重新定义Command联合类型
type Command = InteractionSupportedCommand | BasicCommand;

// 重新定义Module的commands,用明确的联合类型替代宽泛的Record
type Module = {
  commands?: Record<string, SimpleCommandResponse | RunFunction | Command>;
};

2. 用类型守卫强化类型推断

在执行命令的逻辑中,添加类型守卫函数,帮助TypeScript收缩类型,避免参数被推断为any:

// 判断是否为支持交互的命令
function isInteractionCommand(cmd: SimpleCommandResponse | RunFunction | Command): cmd is InteractionSupportedCommand {
  return typeof cmd === 'object' && 'acceptsInteraction' in cmd && cmd.acceptsInteraction === true;
}

// 判断是否为普通Command对象
function isBasicCommand(cmd: SimpleCommandResponse | RunFunction | Command): cmd is BasicCommand {
  return typeof cmd === 'object' && (!('acceptsInteraction' in cmd) || cmd.acceptsInteraction === false);
}

// 命令执行示例
async function executeCommand(cmd: SimpleCommandResponse | RunFunction | Command, trigger: Message | CommandInteraction, args?: string) {
  if (typeof cmd === 'string') {
    // 处理直接回复字符串的命令
    await sendResponse(trigger, cmd);
  } else if (typeof cmd === 'function') {
    // 处理普通RunFunction,仅允许Message触发
    if (trigger instanceof Message) {
      await cmd(trigger, args || '');
    }
  } else if (isInteractionCommand(cmd)) {
    // 处理支持交互的命令
    await cmd.run(trigger, args);
  } else if (isBasicCommand(cmd)) {
    // 处理普通Command对象,仅允许Message触发
    if (trigger instanceof Message) {
      await cmd.run(trigger, args || '');
    }
  }
}

// 统一发送响应的工具函数
async function sendResponse(trigger: Message | CommandInteraction, content: string | MessagePayload | MessageCreateOptions) {
  if (trigger instanceof Message) {
    await trigger.reply(content);
  } else {
    await trigger.reply(typeof content === 'string' ? content : { ...content });
  }
}

3. 可选优化:标签联合类型(Tagged Union)

如果后续需要扩展更多命令类型,建议给每个命令类型添加明确的type标签,进一步提升类型推断的可靠性:

type RunFunction = (message: Message, arg: string) => Awaitable<string | MessagePayload | MessageCreateOptions | void>;

type SimpleCommand = {
  type: 'simple';
  response: string;
};

type BasicFunctionCommand = {
  type: 'basic-function';
  run: RunFunction;
};

type InteractionCommand = {
  type: 'interaction';
  run: (interactionOrMessage: CommandInteraction | Message, arguments?: string) => Awaitable<string | MessagePayload | MessageCreateOptions | void>;
};

// 所有命令类型的联合
type Command = SimpleCommand | BasicFunctionCommand | InteractionCommand;

type Module = {
  commands?: Record<string, Command>;
};

这种方式下,只需判断type字段就能精准区分命令类型,彻底避免联合类型模糊导致的推断问题。


内容的提问来源于stack exchange,提问作者Histmy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 16:45:01