TypeScript:创建输入相互依赖的函数的问题求助
解决方案与解释
问题根源
你的代码中,TypeScript将传入的[A1, A1, A2]推断为联合类型数组(typeof A1 | typeof A2)[],而非保留元素顺序的元组类型。这导致loadInstructions的参数被推断为任意数量的A1 | A2联合类型,既不限制参数数量,也无法匹配对应位置的具体类型。同时,原代码未处理非构造函数类型的parsers元素,会导致InstanceType报错。
修正后的代码
class Result {} function init<P extends readonly any[]>( route: string, parsers: P, loadInstructions: (...data: { [I in keyof P]: P[I] extends new (...args: any[]) => infer Instance ? Instance : P[I] }) => Result ): Result { // 模拟解析逻辑:根据parsers生成对应实例/值 const parsedData = parsers.map((item) => { if (typeof item === 'function' && 'prototype' in item) { // 假设从JSON字符串解析后构造实例 return new item(); } return item; }) as unknown as { [I in keyof P]: P[I] extends new (...args: any[]) => infer Instance ? Instance : P[I] }; return loadInstructions(...parsedData); } // 测试用例 class A1 { name: string; } class A2 { address: string; } // 类型完全匹配的调用 init("/user", [A1, A1, A2], (a: A1, b: A1, c: A2) => { return new Result(); }); // 支持非构造函数类型的parsers init("/config", [A1, "default", 3000], (a: A1, str: string, num: number) => { return new Result(); });
关键改进点
强制元组类型推断
使用P extends readonly any[]作为泛型约束,让TypeScript将传入的数组字面量推断为只读元组,保留每个元素的具体类型和顺序,而非合并为联合类型数组。兼容任意类型的parsers
通过条件类型P[I] extends new (...args: any[]) => infer Instance ? Instance : P[I]处理所有类型的元素:- 如果元素是构造函数,自动提取其实例类型
- 如果是非构造函数(如字符串、数字),直接使用元素本身的类型
严格匹配参数数量与类型
映射后的元组类型作为loadInstructions的剩余参数,确保参数数量、顺序、类型完全对应parsers数组的元素类型,不符合时会直接抛出类型错误。
额外建议
- 如果需要支持可修改的数组(非只读),可以将泛型约束改为
P extends any[],但调用时需要添加as const断言(如[A1, A1, A2] as const),不过会增加调用者的负担,推荐优先使用只读元组方案。 - 若需要更严格的构造函数校验,可以调整条件类型为
P[I] extends new (...args: any[]) => any ? InstanceType<P[I]> : never,但会限制parsers只能传入构造函数类型,不符合你“接受任意类型”的需求。
内容的提问来源于stack exchange,提问作者Martin Nielsen
相关产品推荐
相关产品推荐

