TypeScript中复用函数参数:限制Derive函数依赖匹配
解决Derivative类中依赖类型精准识别的问题
问题描述
我定义了泛型类Dependency<T>用于存储类型为T的值,现在要实现Derivative类,它接收依赖数组和derive函数生成新值。期望限制derive函数仅能使用构造器第一个参数传入的依赖,且能准确识别每个依赖的具体类型(而非合并为联合类型)。当前因类型合并导致编译错误,需要实现对构造器传入依赖的精准引用。
原始代码示例
class Dependency<T> { value: T // 其他实现 } type DependencyArray = Array<Dependency<any>> type DeriveFunc<T, D extends DependencyArray = DependencyArray> = (...deps: D) => Promise<T> class Derivative<T, D extends DependencyArray = DependencyArray> { value: T constructor( dependencies: D, derive: DeriveFunc<T, D>, ) { /* 构造器实现 */ } }
问题场景
const depA = new Dependency<string>() const depB = new Dependency<boolean>() // 正常编译 const der = new Derivative<string>([depA, depB], async ([a, b]) => `${a}-${b}`) // 数组长度不匹配编译失败(符合预期) const der1 = new Derivative<string>([depA, depB], async ([a]) => `${a}`) const der2 = new Derivative<string>([depA], async ([a, b]) => `${a}`) // 类型合并导致编译错误(不符合预期:a被识别为string|boolean,无法访问length) const der3 = new Derivative<string>([depA, depB], async ([a, b]) => `${a.length}-${b}`)
问题分析
原始代码中DependencyArray是普通数组类型,TypeScript会将数组元素的类型合并为联合类型,导致derive函数无法区分每个依赖的具体类型。要解决这个问题,需要让TypeScript保留依赖数组的元组类型,精准追踪每个元素的类型。
解决方案
通过泛型元组替代普通数组类型,让TypeScript保留每个依赖的具体类型信息:
修改后的代码
class Dependency<T> { value: T; // 其他实现 } // 将元组的每个元素映射为对应的Dependency类型 type DependencyTuple<T extends any[]> = { [K in keyof T]: Dependency<T[K]> }; // 提取依赖元组中每个元素的value类型,作为derive函数的参数 type DeriveFunc<T, D extends DependencyTuple<any>> = (...deps: { [K in keyof D]: D[K]['value'] }) => Promise<T>; // 优化泛型推导,让TypeScript自动识别依赖元组类型 class Derivative<T> { value: T; constructor<D extends any[]>( dependencies: DependencyTuple<D>, derive: DeriveFunc<T, DependencyTuple<D>>, ) { // 构造器实现逻辑示例: // this.value = await derive(...dependencies.map(dep => dep.value)); } }
测试验证
const depA = new Dependency<string>(); const depB = new Dependency<boolean>(); // 正常编译,a自动识别为string,b自动识别为boolean const der = new Derivative<string>([depA, depB], async (a, b) => `${a}-${b}`); // 数组长度不匹配编译失败(符合预期) const der1 = new Derivative<string>([depA, depB], async (a) => `${a}`); // 参数数量不匹配报错 const der2 = new Derivative<string>([depA], async (a, b) => `${a}`); // 参数数量不匹配报错 // 类型识别正常,编译通过 const der3 = new Derivative<string>([depA, depB], async (a, b) => `${a.length}-${b}`);
核心原理
- 使用
DependencyTuple<T>将类型元组T的每个元素映射为对应的Dependency类型,保留元组的结构和每个元素的具体类型。 DeriveFunc通过索引类型提取依赖元组中每个元素的value类型,作为函数的参数类型,确保derive函数能精准访问每个依赖的类型属性。- 调整
Derivative的泛型参数,让TypeScript自动推导依赖元组的类型,不需要手动声明。
内容的提问来源于stack exchange,提问作者roboslone
相关产品推荐
相关产品推荐

