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

TypeScript开发discord.js v13机器人报require(...) is not a constructor错误如何解决

问题修复方案

错误原因

这个报错本质是两个核心问题叠加导致的:

  • 你的命令类使用具名导出,require()返回的是包含所有导出内容的对象,而非直接的构造函数,直接调用new require(xxx)自然会提示不是构造函数
  • 命令类的构造函数要求传入HeavensBot客户端实例,你当前初始化时没有传入任何参数,就算导出逻辑正确也会报错

另外还有两处隐藏的逻辑问题:

  • 你在Base基类里把help、conf属性声明为private,外部代码无法直接访问,后续设置命令和别名时也会抛出访问权限错误
  • 你使用了异步回调式的fs.readdir,外层的async关键字没有实际作用,也没有统一的错误捕获逻辑

修复步骤

1. 调整命令类的导出方式(二选一即可)

方案A:改为默认导出

把每个命令文件的导出逻辑改为默认导出,以Ping命令为例:

import { Message } from "discord.js";
import { HeavensBot } from "../HeavensBot";
import { Command as Base } from "../util/Base";

// 把原来的export class Ping改成默认导出
export default class Ping extends Base {
    constructor(client: HeavensBot) {
        super(client, {
            name: "ping",
            description: "Ping command",
            aliases: [],
        });
    }

    run(message: Message, args: string[]) {
        const start = Date.now();

        message.reply({
            content: `Pong! Took ${Date.now() - start}ms`,
        });
    }
}

方案B:保留具名导出

如果不想修改现有导出方式,后续加载时指定对应导出的类名即可。


2. 修改Base基类的属性访问权限

把help和conf的private修饰符改为public,或者单独添加对应的getter方法:

import { HeavensBot } from "../HeavensBot";

interface CommandOptions {
    name: string;
    description: string;
    aliases: string[];
}

interface CommandDotHelp {
    name: string;
    description: string;
}

interface Configuration {
    aliases: string[];
}

export class Command {
    private client: HeavensBot;
    // 把private改为public允许外部访问
    public help: CommandDotHelp;
    public conf: Configuration;

    constructor(client: HeavensBot, options: CommandOptions) {
        this.client = client;
        this.help = {
            name: options.name,
            description: options.description,
        }
        this.conf = {
            aliases: options.aliases,
        }
    }
}

3. 重写loadCommands加载函数

修复加载逻辑,补充参数传入,建议用fs的Promise API适配async异步写法,同时解决路径适配问题:

import { promises as fs } from 'fs';
import path from 'path';

async loadCommands(): Promise<void> {
  try {
    const commandPath = path.resolve(__dirname, './Commands');
    const files = await fs.readdir(commandPath);
    
    for (const file of files) {
      // 过滤非代码文件
      if (!file.endsWith('.ts') && !file.endsWith('.js')) continue;
      // 去掉后缀获取模块名
      const fileName = file.slice(0, file.lastIndexOf('.'));
      // 导入模块:方案A默认导出取.default
      const CommandClass = require(path.join(commandPath, fileName)).default;
      // 如果用方案B具名导出,类名和文件名一致的话用下面的写法
      // const CommandClass = require(path.join(commandPath, fileName))[fileName];
      
      // 传入当前client实例初始化命令
      const command = new CommandClass(this);
      this.commands.set(command.help.name, command);
      command.conf.aliases.forEach((alias: string) => {
        this.aliases.set(alias, command.help.name);
      });
    }
  } catch (err) {
    console.error('命令加载失败:', err);
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 11:36:03