动态导入文件时使用instanceof表达式触发类型报错的问题咨询
报错核心原因
instanceof 运算符的语法规则是:右侧操作数必须是可调用的构造函数(也就是类本身),不能是类创建出来的实例对象。
你代码里触发报错的根因是传参类型定义错误:
- 你给
loadItems定义的第二个参数item类型是Instance extends Item,这个类型指代的是Item子类的实例,不是类构造函数本身,TS识别到它不符合instanceof右侧的类型要求,就抛出了对应错误。
举个直观的例子:
class A {} const aInstance = new A() console.log(aInstance instanceof A) // 正确,右侧是类A(构造函数) console.log(aInstance instanceof aInstance) // 错误,右侧是实例,和你遇到的报错一致
代码里的其他附带问题
除了上面的核心类型错误,你的代码还有两个运行时/逻辑错误:
- 变量名笔误:前面动态导入拿到的对象叫
importFolder,后面循环遍历的时候写成了requireFolder,运行时会直接报变量未定义 - 集合判断错误:你定义的
ItemCollection联合类型是Map | Array,但loadItem方法里判断的是collection instanceof Collection,JS/TS内置没有叫Collection的全局类,这里判断永远不成立,应该改成判断是否为Map实例
修正后的代码
首先补充构造函数类型,用来指代Item子类本身,和实例类型做区分,再修正上述笔误和逻辑错误:
import path from "path"; import fs from "fs"; export abstract class Item { // 提前声明公共属性name,避免后续set操作报类型错误 abstract name: string; } // 构造函数类型:代表Item的子类本身,可通过new创建实例 type ItemCtor<Instance extends Item> = new (...args: any[]) => Instance; export type ItemCollection<Instance extends Item> = | Map<string, Instance> | Instance[]; export class Loader { private loadItem<Instance extends Item>( collection: ItemCollection<Instance>, item: Instance ) { if (collection instanceof Map) { collection.set(item.name, item); } else { collection.push(item); } } public async loadItems<Instance extends Item>( collection: ItemCollection<Instance>, // 参数改为接收构造函数(类本身),命名改成ItemClass方便区分 ItemClass: ItemCtor<Instance>, dirs: string[] ) { for (const dir of dirs) { const files = /* 补全你获取目录下文件路径的逻辑 */ for (const file of files) { const importFolder = await import(file); for (const exportedItem in importFolder) { const importedInstance = importFolder[exportedItem]; // 右侧传入类构造函数,类型校验通过 if (!(importedInstance instanceof ItemClass)) continue; this.loadItem(collection, importedInstance); } } } } }
调用方法时注意传入类本身,不要传实例:
class Weapon extends Item { name: string constructor(name: string) { super() this.name = name } } const loader = new Loader() const weaponMap = new Map<string, Weapon>() // 正确传参:直接传Weapon类,不要new Weapon() loader.loadItems(weaponMap, Weapon, ["./weapon-dir"])
内容的提问来源于stack exchange,提问作者abisammy
相关产品推荐
相关产品推荐

