TypeScript如何定义成员类型匹配对象属性类型的泛型数组?
解决思路与代码修正
一、修正Cells类型与getCells函数
你的核心需求是让Cells<Row>成为一个元组,每个元素的value类型对应Row属性的类型(第一个元素value是number,第二个是string)。原代码的问题在于Cells<T>的定义错误,且函数类型参数未正确使用。以下是修正后的代码:
interface Row { first: number; second: string; } // 提取T的属性键并保持声明顺序,生成键的元组 type Keys<T> = keyof T extends infer K ? K extends string ? [K, ...Keys<Omit<T, K>>] : never : never; // 定义Cells为对应属性值类型的元组,每个元素是{ value: 对应类型 } type Cells<T> = { [I in keyof Keys<T>]: { value: T[Keys<T>[I]] } }; const r: Row = { first: 1, second: "Hi" }; console.log(r); // 函数参数使用泛型T,返回Cells<T>类型 function getCells<T extends Record<string, unknown>>(r: T): Cells<T> { // 通过类型断言让TS识别返回结果为对应元组类型 return Object.values(r).map(v => ({ value: v })) as Cells<T>; } // 调用时TS会自动推断泛型,无需显式传入 const cells = getCells(r); // 此时cells[0].value为number类型,cells[1].value为string类型 console.log(cells);
关键说明:
Keys<T>:递归提取对象的属性键并保持声明顺序,生成键的元组(比如Keys<Row>是['first', 'second'])。Cells<T>:通过映射键元组的每个索引位置,将对应属性值类型作为value的类型,最终生成符合需求的元组类型。getCells函数:使用泛型T接收输入对象,返回Cells<T>;由于Object.values返回的是数组而非元组,需要用as Cells<T>做类型断言让TS识别顺序。
二、TypeScript中Array-like对象的用法
Array-like对象指的是拥有length属性且可通过数字索引访问元素,但不是Array实例的对象,比如arguments、DOM中的NodeList、HTMLCollection等。
1. 定义Array-like类型
在TypeScript中,有两种常见方式定义Array-like类型:
- 只读场景直接用
readonly T[]:type StringArrayLike = readonly string[]; - 手动定义包含
length和数字索引的接口:interface NumberArrayLike { length: number; [index: number]: number; }
2. 转换为真正的数组
Array-like对象没有Array的内置方法(如map、filter),通常需要先转换成数组:
- 使用
Array.from():const nodeList: NodeList = document.querySelectorAll('div'); const divArray: HTMLElement[] = Array.from(nodeList); - 使用扩展运算符
...:const argsArray: any[] = [...arguments];
3. 示例:处理Array-like参数
function sum(arrLike: { length: number; [index: number]: number }): number { let total = 0; for (let i = 0; i < arrLike.length; i++) { total += arrLike[i]; } return total; } // 传入自定义Array-like对象 console.log(sum({ length: 3, 0: 1, 1: 2, 2: 3 })); // 输出6
内容的提问来源于stack exchange,提问作者dbrugger
相关产品推荐
相关产品推荐

