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

如何在类工厂中多态使用类类型参数且避免any类型?

用unknown替代any实现TypeScript类工厂的正确方案

直接使用unknown[]作为构造函数的参数类型会导致外部调用时构造签名不兼容,核心原因是TypeScript中构造签名的参数属于逆变位置,宽泛的unknown[]无法匹配具体的参数类型数组。解决这个问题的关键是用泛型捕获具体的构造参数类型,而非直接使用unknown[]硬编码。

正确实现代码

首先定义泛型构造类型,用unknown替代any作为默认类型约束:

type Constructor<T = unknown, Args extends unknown[] = unknown[]> = new (...args: Args) => T;

然后实现类工厂函数,通过泛型推导捕获目标类的构造参数和实例类型:

function createInstance<T, Args extends unknown[]>(ctor: Constructor<T, Args>, ...args: Args): T {
  return new ctor(...args);
}

使用示例

比如定义一个带具体构造参数的类:

class User {
  constructor(public username: string, public email: string) {}
}

// 内部调用
const user = createInstance(User, "john_doe", "john@example.com");
console.log(user.username); // 类型推导为string,无错误

// 外部依赖调用(比如另一个模块导入此工厂函数)
// 同样可以正确推导参数类型,不会出现构造签名不兼容问题

为什么之前的方案会出错

当你直接定义type SymbolConstructor = new (...args: unknown[]) => symbol时,外部传入的类构造函数(比如new (username: string, email: string) => User)的参数类型是更具体的数组,而逆变位置要求传入的类型必须等于或更窄于声明的类型。unknown[]是最宽泛的数组类型,无法匹配具体的参数数组,因此会触发类型错误。

而泛型版本通过Args推导目标类的具体参数类型,让构造签名的参数类型完全匹配,从根本上解决了不兼容问题,同时全程使用unknown替代any,保持类型安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 17:42:03