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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 05:30:55