TypeScript泛型函数参数报错:类型被当作值使用问题
问题原因
Instance是TypeScript的泛型类型参数,仅存在于类型检查阶段,编译为JavaScript后会被完全擦除,运行时没有对应的实体值。typeof和instanceof都是JavaScript的运行时语法,需要操作实际存在的JS值,因此直接对泛型参数使用typeof会触发'Instance' only refers to a type, but is being used as a value here报错。
解决方案
instanceof校验的右侧必须是实际存在的、带原型链的构造函数值,你只需要把待匹配的Item子类(实际的类构造器)作为显式参数传入方法,让TypeScript根据传入的构造器自动推导泛型对应的实例类型即可,不需要手动通过泛型获取类型。
由于你的Item是抽象类,定义构造器参数类型时注意兼容类的构造签名,修正后的完整代码如下:
import type { Collection } from "对应Collection类型的引入路径"; export abstract class Item { // ... 定义Item的通用属性,例如name等 } // Item集合类型:支持字符串键的Collection结构,或者实例数组 export type ItemCollection<Instance extends Item> = | Collection<string, Instance> | Instance[]; export class Loader { public async loadItems<Instance extends Item>( collection: ItemCollection<Instance>, // 传入实际的类构造器作为运行时校验依据 itemCtor: new (...args: any[]) => Instance, dirs: string[] ) { // 加载逻辑参考: // 1. 遍历dirs下的所有文件做动态import // 2. 读取模块导出的实例,通过 loaded instanceof itemCtor 做合法性校验 // 3. 校验通过的实例加入传入的collection即可 } }
调用方式
调用方法时直接传入具体的Item子类作为第二个参数,TypeScript会自动推导泛型Instance的类型,不需要手动声明泛型:
// 定义具体的Item子类 class Weapon extends Item { attack: number = 10; } const weaponList: Weapon[] = []; const loader = new Loader(); // 传入Weapon类作为构造器参数,自动推导Instance为Weapon类型 await loader.loadItems(weaponList, Weapon, ["./modules/weapons"]);
如果你需要支持传入抽象类作为校验基准(校验实例是否继承自某个抽象类),可以把itemCtor的类型修改为abstract new (...args: any[]) => Instance,该签名同时兼容抽象类和普通可实例化的具体类。
内容的提问来源于stack exchange,提问作者abisammy
相关产品推荐
相关产品推荐

