Object.keys 的原生 JS 类型之困

前言

TS 项目开发时,大家想必都遭遇过一个颇为头疼的状况:原生 JS 的一些方法,类型定义并不完善。日常编码中,这就像个小 "绊脚石",你本想高效推进项目,却常常因为它,不得不暂停下来,写一堆额外代码去弥补类型缺失带来的隐患,无端耗费许多精力,别提多闹心了。

被被这问题纠缠久了,我实在忍无可忍。与其每次都临时抱佛脚应付,不如主动出击,彻查根源,找个能彻底改善局面的法子。

下面,我打算以 Object.keys 为典型案例,进行深入剖析,旨在为面临同样困境的开发者提供有益的参考与启发。

问题描述

深入探究 Object.keys 原始的类型定义,可归纳出两个关键特征:

通过上面代码我们可以看到两个点

  1. 该方法隶属于 ObjectConstructor 范畴。
  2. 其参数类型仅被简单定义为 object,返回值类型为 string[],且不支持泛型这一特性,致使其类型表达能力受限。

如此的类型设定,在实际编码中极易引发问题。参考以下示例代码

typescript 复制代码
const obj = { aaa: "0001", bbb: "0002" };

Object.keys(obj).forEach((key) => {
  obj[key] // 类型报错
  ~~~~~~~~
  // 元素隐式具有 "any" 类型,因为类型为 "string" 的表达式不能用于索引类型 "{ aaa: string; bbb: string; }"。
  // 在类型 "{ aaa: string; bbb: string; }" 上找不到具有类型为 "string" 的参数的索引签名。
});

由上述代码可见,当使用 Object.keys 提取对象的可枚举属性名,并尝试基于这些属性名迭代获取对应属性值时,类型错误便随之产生。

面对此类问题,部分开发者可能会采取临时的类型断言措施,如 (Object.keys(obj) as (keyof typeof obj)[]).forEach...。然而,这种方式仅能解一时之急,无法满足代码准确性与简洁性的长远需求。开发者真正期望的是,Object.keys 能够智能、精准地依据对象实例推导其包含的属性信息,而非仅仅返回一个宽泛的 string[]

基于对该问题的深度困扰,探索如何重塑 Object.keys 的类型,以实现精准的类型推导,成为解决问题的关键思路。经研究发现,利用全局类型声明文件覆盖原有的类型定义,是一条可行的解决路径。

解决方案

  1. 首先,创建一个以 .d.ts 结尾的文件,此类文件作为类型声明文件,在 TS 项目的类型管理体系中发挥着关键作用。
  2. 鉴于前文对 Object.keys 所属范畴的分析,需在类型声明文件中对 ObjectConstructor 进行针对性处理。具体操作如下:
typescript 复制代码
// window.d.ts

interface ObjectConstructor {
  keys<T>(o: T): (keyof T)[]; // 覆盖 Object.keys 的类型
}

值得一提的是,通过 interface 在类型声明文件中声明的类型,具备全局可用性,能够在整个项目代码范围内有效约束类型,保障代码的类型安全性。

经上述改造后,再次使用 Object.keys 时,令人欣喜的是,其已能够自动推导出精准的返回值类型,如 ("aaa" | "bbb")[],达成了预期的优化效果。

相关推荐
破浪前行·吴25 分钟前
【初体验】【学习】Web Component
前端·javascript·css·学习·html
染指悲剧2 小时前
vue实现虚拟列表滚动
前端·javascript·vue.js
浩浩测试一下4 小时前
Web渗透测试之XSS跨站脚本之JS输出 以及 什么是闭合标签 一篇文章给你说明白
前端·javascript·安全·web安全·网络安全·html·系统安全
肖老师xy5 小时前
h5使用better scroll实现左右列表联动
前端·javascript·html
一路向北North5 小时前
关于easyui select多选下拉框重置后多余显示了逗号
前端·javascript·easyui
Libby博仙5 小时前
.net core 为什么使用 null!
javascript·c#·asp.net·.netcore
一水鉴天5 小时前
为AI聊天工具添加一个知识系统 之26 资源存储库和资源管理器
前端·javascript·easyui
万物得其道者成6 小时前
在高德地图上加载3DTilesLayer图层模型/天地瓦片
前端·javascript·3d
你挚爱的强哥6 小时前
基于element UI el-dropdown打造表格操作列的“更多⌵”上下文关联菜单
javascript·vue.js·elementui