TypeScript枚举用Object.keys获键含索引值及动态过滤属性问题
问题解答
一、为什么Object.keys(IAgentTask)会返回数字索引?
你定义的是TypeScript的数字枚举,这类枚举编译为JavaScript时会生成双向映射的对象:
- 正向映射:字符串键(如
firstName)对应自动分配的数字值(从0开始递增) - 反向映射:数字值对应回字符串键
编译后的代码大致如下:
export var IAgentTask; (function (IAgentTask) { IAgentTask[IAgentTask["firstName"] = 0] = "firstName"; IAgentTask[IAgentTask["lastName"] = 1] = "lastName"; // ...其余枚举项的映射 })(IAgentTask || (IAgentTask = {}));
所以Object.keys(IAgentTask)会把正向的字符串键和反向的数字转字符串键('0'、'1'...)一起返回,这就是你看到数字索引的原因。
如果只想获取枚举的纯字符串键,可以过滤掉数字类型的键:
const enumStringKeys = Object.keys(IAgentTask).filter(key => isNaN(Number(key)));
二、如何正确过滤response.tasks的属性?
你的原有代码有两个核心问题:
- 使用
for (let key in Object.keys(IAgentTask))遍历数组时,拿到的是数组索引('0'、'1'这类字符串),而非枚举键名,导致response.tasks[j][key]始终为undefined - 直接遍历枚举键处理task属性不够准确,应该针对每个task自身的属性做过滤
推荐实现(创建新对象保留允许字段,避免修改原对象)
const allowedFields = new Set(this.filteredRowsPreference.map(x => x.fieldDbKey)); // 遍历每个任务,生成只保留允许字段的新对象 response.tasks = response.tasks.map(task => { const filteredTask: Partial<typeof task> = {}; Object.keys(task).forEach(key => { if (allowedFields.has(key)) { filteredTask[key] = task[key]; } }); return filteredTask as typeof task; });
若需直接删除属性(不推荐,会修改原对象)
const allowedFields = new Set(this.filteredRowsPreference.map(x => x.fieldDbKey)); for (const task of response.tasks) { // 遍历当前任务的所有属性键 Object.keys(task).forEach(key => { if (!allowedFields.has(key)) { delete task[key]; } }); }
补充说明
- 用
Set存储允许字段是为了提升查询效率(从O(n)优化为O(1)),字段数量少时用数组includes也可行 - 直接遍历task自身的属性,比遍历枚举键更准确,避免枚举键与task属性不匹配的问题
内容的提问来源于stack exchange,提问作者questions ss
相关产品推荐
相关产品推荐

