Discord.js机器人实现禁言命令时触发TypeError: fn is not a function报错
报错根因
调用discord.js内置Collection类的find()方法时,未按规范传入函数类型的判断回调,直接将字符串类型的参数传入了首个形参位置,直接触发类型校验报错。
报错对应模块的执行逻辑:
find(fn, thisArg)方法的首个入参fn必须是可执行函数,方法内部会遍历集合内所有元素,将每个元素、对应键值、集合实例本身作为参数传入fn执行,当fn返回真值时返回对应元素。如果传入的fn不是函数类型,内部执行fn(val, key, this)时就会抛出TypeError: fn is not a function。
触发报错的业务代码片段:
const target = message.guild.members.cache.find(args[0])
其中args[0]是命令解析出的字符串值,并非函数类型,刚好命中报错触发条件。
除了核心类型报错之外,现有代码还存在两个连带风险:
- 如果
find方法未匹配到对应成员,会返回undefined,后续执行target.roles.forEach时会抛出空对象引用错误 - 代码中外层包裹的
console.log()无实际作用,forEach执行后无返回值,外层只会输出无意义的undefined
修复方案
- 严格匹配
Collection.find()的入参要求,传入判断逻辑对应的回调函数,以通过传入参数匹配服务器成员为例,正确写法为:// 遍历成员缓存,匹配ID和传入参数一致的成员 const target = message.guild.members.cache.find(member => member.id === args[0]) - 增加空值兜底判断,避免匹配失败引发的连带报错:
if (!target) { return message.reply("未查询到对应服务器成员") } // 直接调用forEach打印角色ID,去掉无意义的外层console.log target.roles.forEach(role => console.log(role.id)) - 实操优化:处理用户命令参数时,可先清洗用户提及格式(比如
<@!123456789>这类提及字符串),提取纯数字用户ID再做匹配,避免格式差异导致的匹配失败。
内容的提问来源于stack exchange,提问作者user15194403
相关产品推荐
相关产品推荐

