如何在TypeScript中正确扩展number等原生基本类型?
问题原因
- TS2345报错:TS中
Number接口对应JS的Number包装对象类型,挂载在Number.prototype上的方法内部this默认推导为Number包装类型,而Math.min/Math.max要求传入基本类型number,二者类型不匹配触发报错。 - TS2427报错:
number是TS内置的基本类型保留关键字,不允许用作自定义接口名称,因此修改为interface number直接报错。 - TS2339报错:TS的基本类型
number默认会自动继承Number接口的成员定义,出现该报错是因为你的全局类型声明未正确生效:要么是声明写在包含import/export的模块文件中,声明合并逻辑未被TS识别;要么是@ts-ignore注解掩盖了类型问题,导致声明链断裂。
正确实现方案
扩展原生基本类型的核心逻辑是正确完成全局接口的声明合并,同时处理好原型方法内的this类型,分两种常用场景实现:
场景1:在普通业务模块(存在import/export)中实现
直接在模块文件中编写如下代码即可:
// 因为当前是模块,扩展全局类型需要放在declare global块中 declare global { interface Number { clamp(min: number, max: number): number; } } // 实现时给this显式指定为number基本类型,绕过包装类型校验 Number.prototype.clamp = function(this: number, min: number, max: number): number { // 也可以不用注解this,改为显式转成基本类型:Math.min(Math.max(Number(this), min), max) return Math.min(Math.max(this, min), max); }; // 加空导出确保TS将当前文件识别为模块,保证declare global生效 export {}
场景2:使用单独的全局声明文件管理类型
- 首先在项目根目录新建
global.d.ts,并确保tsconfig.json的include配置项包含该文件,写入类型声明:
// 该文件不要添加任何import/export,保证是全局作用域文件 interface Number { clamp(min: number, max: number): number; }
- 然后在任意项目初始化阶段执行的代码文件中写入实现逻辑:
Number.prototype.clamp = function(this: number, min: number, max: number): number { return Math.min(Math.max(this, min), max); };
完成后即可直接在number类型变量上调用clamp方法,不会再出现类型报错。
内容的提问来源于stack exchange,提问作者Khryus
相关产品推荐
相关产品推荐

