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

如何编写TypeScript函数接收子类型继承父类型的元组数组?

如何编写约束元组数组元素子类型关系的TypeScript函数

要实现接收元组数组且每个元组第二个元素是第一个元素子类型(类构造函数而非实例)的函数,有两种简洁的实现方式:

方案一:精准约束类构造函数类型

如果你的场景只针对类(包括抽象类),可以直接定义符合要求的元组类型,再约束参数为该类型的数组:

// 定义合法元组:第一个是抽象/普通类构造函数,第二个是其子类构造函数
type ValidClassTuple = [
  Base: abstract new (...args: any[]) => any,
  Sub: new (...args: any[]) => InstanceType<typeof Base>
];

function foo(x: ValidClassTuple[]): void {}

// 测试示例
abstract class A {
  abstract foo(): any
}
class B extends A {
  foo() { throw new Error("Method not implemented.") }
}
abstract class C {
  abstract baz(): any
}
class D extends C {
  baz() { throw new Error("Method not implemented.") }
}

// 合法调用:通过类型校验
foo([
 [A, B],
 [C, D]
])

// 非法调用:报错,C不是A的子类
// foo([[A, C]])

这个方案直接针对类构造函数做约束,类型检查更精准,能避免传入非类类型的错误。

方案二:通用子类型约束(支持任意类型)

如果需要支持更通用的子类型关系(不局限于类),可以利用你之前定义的ValidateTuples类型,将其作为函数参数的约束:

type ValidateTuples<T> = T extends Array<[any, any]>
  ? {
      [K in keyof T]: T[K] extends [infer A, infer B]
        ? B extends A
          ? T[K]
          : never
        : never
    }
  : never;

// 泛型T捕获传入的数组类型,再用ValidateTuples约束其合法性
function foo<T extends Array<[any, any]>>(x: ValidateTuples<T>): void {}

// 同样支持合法调用,非法调用会触发类型错误
foo([[A, B], [C, D]])
// foo([[A, C]]) // 报错

分析你之前的尝试问题

  • 单泛型约束失效:function foo<A, B extends A>(x: Array<[A, B]>) {}的问题在于,泛型A和B是全局的,要求数组中所有元组都必须使用同一组A和B。当你传入不同Base的元组(比如[A,B]和[C,D]),TypeScript无法找到一个统一的A满足所有元组,因此报错。
  • ValidateTuples的正确用法:你定义的ValidateTuples类型本身是有效的,只需将它和泛型T结合,让函数参数的类型为ValidateTuples<T>,同时用T捕获传入的原始数组类型,就能实现动态校验每个元组的子类型关系。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 17:33:10