首页 前端 正文

[译] 技巧43:用类型安全的方法打猴子补丁

本文的翻译于\<\>, 特别感谢!! ps: 本文会用简洁, 易懂的语言描述原书的所有要点. 如果能看懂这文章,将节省许多阅读时间. 如果看不懂,务必给我留言, 我回去修改.

技巧43:用类型安全的方法打猴子补丁

js最出名的一个特性就是:所有的对象,类都是开放的,也就是你可以给其添加任意属性。利用这一特性给window和document添加属性,这也就意味着添加了全局变量:

window.monkey = 'Tamarin';
document.monkey = 'Howler';

或者利用这一特性给DOM元素添加数据:

const el = document.getElementById('colobus');
el.home = 'tree';

这种风格在jQuery代码中十分常见。

你甚至可以在原型上添加属性:

>  RegExp.prototype.monkey = 'Capuchin' 
"Capuchin"
>  /123/.monkey
"Capuchin"

这种方法通常不是好的代码设计,给window和document添加属性,这也就意味着添加了全局变量。这有可能在不经意间,给两个毫无关系的程序添加依赖。也就意味着,你调用一个函数你必须考虑会引起的副作用。

同时,当引入ts后,这种设计也会有问题:ts知道window,document的类型,但是不知道你新增属性的类型:

document.monkey = 'Tamarin';
      // ~~~~~~ Property 'monkey' does not exist on type 'Document'

最直接的修复这个错误的方式:any断言

(document as any).monkey = 'Tamarin';  // OK

这能通过ts的类型检查,与此同时你失去了类型安全和语言服务:

(document as any).monky = 'Tamarin';  // Also OK, misspelled
(document as any).monkey = /Tamarin/;  // Also OK, wrong type

当你必须给document或者说是DOM元素添加data,有一个更好的办法:类型增强,这也是interface最特别的能力:

interface Document {
  /** Genus or species of monkey patch */
  monkey: string;
}

document.monkey = 'Tamarin';  // OK

这和any断言相比有几处改进:

  • 获得了类型安全:类型检查能检查出你的拼写错误,和类型错误。

  • 你可以将documentation加到property

  • 获得属性的自动补全

  • 能获得猴子补丁的确切记录 在模块上下文中(import,export),你需要添加declare global让其生效:

    export {};
    declare global {
    interface Document {
      /** Genus or species of monkey patch */
      monkey: string;
    }
    }
    document.monkey = 'Tamarin';  // OK

    这种类型增强主要的问题在于范围:

  • 类型增强用于全局,你无法在部分代码中隐藏。

  • 因为类型增强发生在你应用运行中,只有类型增强这段代码运行后,才能获得改全局变量,再次之前没有。这也就意味着,当你想获得这个全局变量,你很难确定其是否存在

更好的方法,用精准的断言:

interface MonkeyDocument extends Document {
  /** Genus or species of monkey patch */
  monkey: string;
}
(document as MonkeyDocument).monkey = 'Macaque';

这种方法能类型安全的对document赋值,同时没有对Document的类型进行全局修改。当你引用这个猴子补丁的时候你需要写断言。

原文:https://juejin.cn/post/7094815719069581325

打赏
海报

本文转载自互联网,旨在分享有价值的内容,文章如有侵权请联系删除,部分文章如未署名作者来源请联系我们及时备注,感谢您的支持。

转载请注明本文地址:https://www.shouxicto.com/article/3641.html

相关推荐

什么是gRPC

什么是gRPC

本文的翻译于\<\>, 特别感谢!! ps: 本文会用简洁, 易懂的语言描述原书的所有要点. 如果能看懂这文章,将节省许多阅...

前端 2022.08.19 0 1393

什么是前端工程化?

什么是前端工程化?

本文的翻译于\<\>, 特别感谢!! ps: 本文会用简洁, 易懂的语言描述原书的所有要点. 如果能看懂这文章,将节省许多阅...

前端 2022.08.19 0 1202

发布评论

ainiaobaibaibaibaobaobeishangbishibizuichiguachijingchongjingdahaqiandaliandangaodw_dogedw_erhadw_miaodw_tuzidw_xiongmaodw_zhutouganbeigeiliguiguolaiguzhanghahahahashoushihaixiuhanheixianhenghorse2huaixiaohuatonghuaxinhufenjiayoujiyankeaikeliankouzhaokukuloukunkuxiaolandelinileimuliwulxhainiolxhlikelxhqiuguanzhulxhtouxiaolxhwahahalxhzanningwennonuokpinganqianqiaoqinqinquantouruoshayanshengbingshiwangshuaishuijiaosikaostar0star2star3taikaixintanshoutianpingtouxiaotuwabiweifengweiquweiwuweixiaowenhaowoshouwuxiangjixianhuaxiaoerbuyuxiaokuxiaoxinxinxinxinsuixixixuyeyinxianyinyueyouhenghengyuebingyueliangyunzanzhajizhongguozanzhoumazhuakuangzuohenghengzuoyi
支付宝
微信
赞助本站