如何约束对象属性为同一类型?TypeScript泛型实现问询
TypeScript异构泛型对象数组的类型定义方案
问题背景
需要创建一个数组,其中每个元素都是Pair<T>类型对象——要求单个对象的a和b属性必须是同一泛型类型T,但数组中不同元素的T可以是任意类型(比如同时包含Pair<number>、Pair<string>)。但直接定义数组类型时遇到了编译器报错:
错误示例代码
type Pair<T> = { a: T b: T } // 报错:泛型类型'Pair'需要1个类型参数 type PairArray = Array<Pair> // 尝试用工厂函数数组,依然报错 type PairFactory = <T>() => Pair<T> type PairArrayFactory = Array<PairFactory> // 报错:T可能被实例化为与'string'无关的任意类型 const pairArrayFactory: PairArrayFactory = [() => {return {a: '', b: ''}}]
期望实现的用法:
const pairArray: PairArray = [ { a: 1, b: 2 }, { a: 'foo', b: 'bar' }, ... ]
可行解决方案
方案1:用Pair<unknown>作为数组元素类型
这是最直接的方式,把数组定义为Pair<unknown>[],它允许数组中包含任意类型的Pair对象,同时保证每个对象内部的a和b类型一致:
type Pair<T> = { a: T b: T } type PairArray = Pair<unknown>[]; const pairArray: PairArray = [ { a: 1, b: 2 }, { a: 'foo', b: 'bar' }, { a: true, b: false } ]; // 使用时可通过类型断言获取具体类型 const numPair = pairArray[0] as Pair<number>; console.log(numPair.a + numPair.b); // 正常执行
方案2:泛型函数自动推导数组类型
如果希望编译器自动推导每个元素的具体类型,同时严格保证单个对象的a、b类型一致,可以用泛型函数来创建数组:
type Pair<T> = { a: T b: T } function createPairArray<T extends unknown[]>(...pairs: { [K in keyof T]: Pair<T[K]> }) { return pairs; } // 编译器自动推导出每个元素的类型 const pairArray = createPairArray( { a: 1, b: 2 }, { a: 'foo', b: 'bar' }, { a: true, b: false } ); // pairArray的类型为:(Pair<number> | Pair<string> | Pair<boolean>)[]
方案3:预定义联合类型(已知所有可能的T时)
如果提前明确数组中可能出现的T类型,可以直接定义联合类型数组:
type Pair<T> = { a: T b: T } // 指定所有允许的Pair类型 type PairArray = (Pair<number> | Pair<string> | Pair<boolean>)[]; const pairArray: PairArray = [ { a: 1, b: 2 }, { a: 'foo', b: 'bar' }, { a: true, b: false } ];
为什么原有写法错误?
Array<Pair>报错:Pair是泛型类型,必须显式指定类型参数,不能直接裸用;- 工厂函数数组报错:
PairFactory定义的是通用泛型函数,要求该函数能适配任意T类型的调用,但你写的工厂函数固定返回string类型的Pair,不符合通用泛型函数的约束,因此编译器报错。
内容的提问来源于stack exchange,提问作者Alex Van de Kleut
相关产品推荐
相关产品推荐

