TypeScript泛型函数构造n元组参数并调用构造器的类型实现问题
TypeScript泛型构造器参数映射函数实现方案
这个需求完全可以实现,当前代码的核心问题有两个:一是构造器参数c的类型未与泛型C绑定,二是原生Array.prototype.map无法保留元组类型,导致params被推断为any[]。下面是修正后的完整实现:
核心类型定义与函数实现
// 更精准的构造器类型定义 type Class<T = any> = abstract new (...args: any[]) => T; type Mapper<Input, Output> = (input: Input) => Output; // 生成与构造器参数一一对应的mapper元组类型 type ConstructorMapperTuple<Input, C extends Class> = { [K in keyof ConstructorParameters<C>]: Mapper<Input, ConstructorParameters<C>[K]>; }; function convert<C extends Class>( stuff: unknown, mappers: ConstructorMapperTuple<unknown, C>, constructor: C ): C extends Class<infer Instance> ? Instance : never { // 带错误处理的参数提取逻辑 const params: ConstructorParameters<C> = [] as any; let hasError = false; const errors: unknown[] = []; for (let i = 0; i < mappers.length; i++) { try { params[i] = mappers[i](stuff); } catch (e) { hasError = true; errors.push(e); console.error(`第${i+1}个mapper执行失败:`, e); } } if (hasError) { throw new Error(`共${errors.length}个mapper执行失败,无法实例化目标对象`); } return new constructor(...params); }
关键修正点说明
- 构造器类型绑定:将参数
constructor的类型设为泛型C,而非宽泛的Class,让TypeScript能精准推导构造器的参数元组类型。 - 元组类型匹配:通过
ConstructorMapperTuple类型,强制mappers数组的每个元素返回值类型,与构造器对应位置的参数类型完全匹配。 - 错误处理逻辑:遍历mappers逐个执行并捕获异常,只有当所有mapper执行成功时才调用构造器生成实例;若有任意失败则抛出汇总错误。
使用示例
// 示例类 class Product { constructor(public sku: string, public price: number, public inStock: boolean) {} } // 对应构造器参数的mapper数组 const productMappers: ConstructorMapperTuple<unknown, typeof Product> = [ (stuff: any) => stuff.sku.trim(), (stuff: any) => Number(stuff.price), (stuff: any) => Boolean(stuff.inStock) ]; // 执行转换 const rawData = { sku: " PROD001 ", price: "99.9", inStock: "true" }; const product = convert(rawData, productMappers, Product); console.log(product); // Product { sku: 'PROD001', price: 99.9, inStock: true }
内容的提问来源于stack exchange,提问作者Harald
相关产品推荐
相关产品推荐

