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")[],达成了预期的优化效果。

相关推荐
样子201826 分钟前
Uniapp 之renderjs解决swiper+多个video卡顿问题
前端·javascript·css·uni-app·html
黑客飓风1 小时前
JavaScript 性能优化实战大纲
前端·javascript·性能优化
YeeWang4 小时前
🎉 Eficy 让你的 Cherry Studio 直接生成可预览的 React 页面
前端·javascript
gnip4 小时前
Jenkins部署前端项目实战方案
前端·javascript·架构
Orange3015114 小时前
《深入源码理解webpack构建流程》
前端·javascript·webpack·typescript·node.js·es6
李明卫杭州5 小时前
CSS `clamp()` 函数详解
javascript
奶丝兔蜜柚5 小时前
栈溢出优化
javascript
小高0076 小时前
📈前端图片压缩实战:体积直降 80%,LCP 提升 2 倍
前端·javascript·面试
BillKu6 小时前
vue3+element-plus 输入框el-input设置背景颜色和字体颜色,样式效果等同于不可编辑的效果
前端·javascript·vue.js
NeilNiu6 小时前
开源AI工具Midscene.js
javascript·人工智能·开源