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

TypeScript如何基于第一个泛型参数条件关联第二个泛型参数

实现方案

你需要使用TypeScript编译期的条件类型来实现泛型参数的依赖关联,不能使用运行时运算符instanceof做泛型约束判断,具体实现如下:

步骤1:定义类型映射规则

先声明一个工具类型,根据传入的原始类型匹配对应的构造函数类型:

type ClassForType<T extends string | number> = 
  T extends string ? typeof StringClass : typeof NumberClass;

步骤2:改写泛型类

这里提供两种写法,按需选择即可:

写法1:省略第二个泛型参数(推荐)

因为B的类型完全由A决定,不需要额外声明第二个泛型,减少冗余:

class Test<A extends string | number> {
    // val存储的是类实例,使用InstanceType工具类取构造函数对应的实例类型
    val: InstanceType<ClassForType<A>>;
    
    constructor(val: A, Class: ClassForType<A>) {
        this.val = new Class(val);
    }
}

写法2:保留第二个泛型参数

如果有场景需要显式声明第二个泛型,可以用约束+默认值的形式:

class Test<
  A extends string | number,
  B extends ClassForType<A> = ClassForType<A>
> {
    val: InstanceType<B>;
    
    constructor(val: A, Class: B) {
        this.val = new Class(val);
    }
}

验证效果

写测试用例可以看到类型约束已经生效:

// 传入字符串时,只允许传入StringClass构造函数
new Test('test', StringClass); // 编译通过
new Test('test', NumberClass); // 编译报错:类型不匹配

// 传入数字时,只允许传入NumberClass构造函数
new Test(123, NumberClass); // 编译通过
new Test(123, StringClass); // 编译报错:类型不匹配

注意点

  • 你原有代码中val: B的定义存在问题:B是构造函数的类型,new Class(val)返回的是类实例,需要用InstanceType<B>获取对应的实例类型赋值给val。
  • instanceof是运行时运算符,不能用在编译期的泛型约束中,同时原始类型string/number的判断用instanceof本身也不符合预期,只有包装对象才会满足instanceof String/Number的判断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 22:12:00