详解Anyscript开发指南绕过typescript类型检查


Posted in Javascript onSeptember 23, 2022

前言

随着越来越多的前端项目采用 typescript 来开发,越来越多前端开发者会接触、使用这门语言。它是前端项目工程化的一个重要帮手,结合 vscode 编辑器,给予了前端开发者更严谨、高效的编码体验。但同时,严格的类型检查也会使部分开发者的编码效率有所降低,将时间花费在解决类型冲突、类型不匹配上,从而导致望而却步,迟迟不敢上手。

本文描述了几种绕过 typescript 类型检查的方法,帮助ts开发者在遇上第三方库类型声明有误、上线时间紧张却还被ts类型耽搁开发进度、以及其他奇奇怪怪ts类型声明的场景时,能够快速摆脱ts类型检测,保障项目尽快上线。

注意,本文所提到的方法,只能作为一种最后不得已的hack手段,其目的是为了尽快完成需求而非代码取巧,读者不应该将其当成一种常用的写法并在项目内任意使用!

场景设定

假设存在一个第三方库,允许开发者通过 json 定义一个表单,其 typescript 类型定义如下:

interface FormItem{
    /** 表单类型 */
    type:string
    /** 显示文本 */
    label:string
}
interface FormSelectItem extends FormItem{  
    /** 将表单类型指定为'select' */
    type:'select'
    /** 新增一个options属性,类型为数组,此类型定义存在错误,没有定义options数组里面的内容 */
    options:[]
}
type FormRule = (FormSelectItem|FormItem)[]

代码里,FormSelectItem.options期望的是一个有内容的数组,但因为第三方库给定的类型文件编写错误,没有给出数组内部项的结构,只留下[]空数组类型定义,导致开发者给FormSelectItem.options赋予一个有内容的数组都会导致 typescript 报错。

详解Anyscript开发指南绕过typescript类型检查

解决方法

注释忽略

//@ts-ignore会让typescript编译器跳过注释下一行代码,不对其进行类型检查。通过不检查类型的方式,绕过类型检查

//@ts-ignore
window.aaaa = "使用示例(ts里不允许通过此行代码往全局对象挂载属性)"

场景用例

详解Anyscript开发指南绕过typescript类型检查

加上//@ts-ignoreoptions属性之上,编译器跳过了options属性的检查,因此报错消失。使用起来十分简单快捷,但是加了注释忽略之后,开发者为options赋予任何值都是合法的,如非数组的对象、null、undefined等容易引起程序出错的类型。同时加了//@ts-ignore之后,编辑器无法再对此行进行代码提示和自动补全。

类型断言

类型断言是typescript中一种将一个类型指定为另一个类型的语法。通过指定任意类型为目标类型的方式,达到编译器不报错的效果。

(window as unknown as {aaa:string}).aaa = "使用示例(ts里不允许通过此行代码往全局对象挂载属性)"

场景用例

详解Anyscript开发指南绕过typescript类型检查

上图使用了断言语法,且用到两种断言方式:

  • 第一种写法是给赋值数据下断言,将数据类型强制断言为定义类型,即在上图中,将{label:string,value:string}[]断言为[],使得能够与options 的类型匹配上。在属性赋值中只能使用此种断言写法。
  • 第二种写法是反过来,通过将定义类型强制断言为数据类型,即在上图中,将[]断言为{label:string,value:string}[],使得select.options能够按照开发者的数据类型进行工作。并且通过此种方式,对select.options进行操作时,编辑器还会根据开发者的断言类型进行语法提示。

相比注释忽略,类型断言原本就是typescript语法的一部分,本身就会接受类型检查,因此后续的代码补全提示功能是完整的。但同时开发者主观上应当明白类型断言的作用,避免将不正确的数据类型传入导致代码出错。

泛型转换

泛型是typescript最强大的功能,它提供给了开发者们对类型“编程”的能力。通过定义泛型辅助函数,在类型断言的基础上,利用函数返回泛型的手段,巧妙地将类型匹配上,从而达到缩小代码量且编译器不报错的效果。

function _any<T>(obj:any):T{
    return obj as unknown as T
}
_any<{aaa:string}>(window).aaa='使用示例(ts里不允许通过此行代码往全局对象挂载属性)'

实际上,辅助函数也只是将参数当作是返回值而已,只不过利用泛型可以指定为任意类型。

甚至可以设置两个泛型:一个是目标泛型,也就是函数要返回的数据类型,一个是参数泛型,也就是传入的数据类型。当显式地赋予泛型P一个类型时,typescript可以为参数提供类型检查和语法补全。

function _any<T,P=any>(obj:P):T{
    return obj as unknown as T
}
const select:FormSelectItem = {
    type:'select',
    options:_any<[],{label:string,value:string}[]>([{
        label:'',
        value:''
    }])
}
_any<{label:string,value:string}[]>(select.options).push({
    label:'',
    value:''
})

场景用例

详解Anyscript开发指南绕过typescript类型检查

相比类型断言,使用泛型转换辅助函数的做法最大的作用,是简化了as unknow as xxx的写法,本质上还是一样的。开发者同样需要明白转类型的作用,避免使用错误的类型导致代码错误。

总结

遇上类型对不上,项目又急着上线,缺乏足够的时间跟typescript编译器慢慢折腾的情况下,可以酌情使用注释忽略、类型断言、泛型转换的方法来强行指定类型。

其中注释忽略是利用编译器跳过的方式,停止类型检查,带来的后果就是该行其他数据无法获得类型校验;

类型断言、泛型转换都通过断言的语法,强行指定类型,使类型对应上,进而通过编译;

而泛型转换是利用辅助函数的写法,来减少断言代码的编写。

但这三种方式都存在风险,开发者都需要明白赋予的数据类型的含义,避免数据错误导致代码出错。

以上就是详解Anyscript开发指南绕过typescript类型检查的详细内容,更多关于Anyscript绕过typescript类型检查的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
js之WEB开发调试利器:Firebug 下载
Jan 13 Javascript
JavaScript中“+=”的应用
Feb 02 Javascript
认识延迟时间为0的setTimeout
May 16 Javascript
JavaScript限定复选框的选择个数示例代码
Aug 25 Javascript
JS不能跨域借助jquery获取IP地址的方法
Aug 20 Javascript
学习JavaScript设计模式之迭代器模式
Jan 19 Javascript
JavaScript重载函数实例剖析
May 13 Javascript
原生js仿浏览器滚动条效果
Mar 02 Javascript
Vue.js中兄弟组件之间互相传值实例
Jun 01 Javascript
详解Angular 中 ngOnInit 和 constructor 使用场景
Jun 22 Javascript
jQuery实现可编辑表格并生成json结果(实例代码)
Jul 19 jQuery
了解重排与重绘
May 29 Javascript
js基于div丝滑实现贝塞尔曲线
Sep 23 #Javascript
TS 类型兼容教程示例详解
Sep 23 #Javascript
TS 类型收窄教程示例详解
Sep 23 #Javascript
JavaScript实现简单的音乐播放器
Aug 14 #Javascript
vue实现简易音乐播放器
Aug 14 #Vue.js
Vue3实现简易音乐播放器组件
Aug 14 #Vue.js
element tree树形组件回显数据问题解决
Aug 14 #Javascript
You might like
收听短波不可能有声音清晰的品质吗
2021/03/01 无线电
PHP 实例化类的一点摘记
2008/03/23 PHP
php 字符串压缩方法比较示例
2014/01/23 PHP
php解决约瑟夫环示例
2014/04/09 PHP
PHP发送短信代码分享
2015/08/11 PHP
php获取图片信息的方法详解
2015/12/10 PHP
jquery Ajax实现Select动态添加数据
2017/06/08 jQuery
JavaScript 值类型和引用类型的初次研究(推荐)
2017/07/19 Javascript
可能被忽略的一些JavaScript数组方法细节
2019/02/28 Javascript
vue倒计时刷新页面不会从头开始的解决方法
2020/03/03 Javascript
使用python实现正则匹配检索远端FTP目录下的文件
2015/03/25 Python
Python程序中使用SQLAlchemy时出现乱码的解决方案
2015/04/24 Python
python 显示数组全部元素的方法
2018/04/19 Python
PyTorch CNN实战之MNIST手写数字识别示例
2018/05/29 Python
如何基于python实现脚本加密
2019/12/28 Python
python实现将两个文件夹合并至另一个文件夹(制作数据集)
2020/04/03 Python
opencv python 图片读取与显示图片窗口未响应问题的解决
2020/04/24 Python
关于Python 解决Python3.9 pandas.read_excel(‘xxx.xlsx‘)报错的问题
2020/11/28 Python
Django模板报TemplateDoesNotExist异常(亲测可行)
2020/12/18 Python
浅谈HTML5新增和废弃的标签
2019/04/28 HTML / CSS
网购亚洲时装、美容产品和生活百货:YesStyle
2016/09/15 全球购物
美国殿堂级滑板、冲浪、滑雪服装品牌:Volcom(钻石)
2017/04/20 全球购物
Bally美国官网:经典瑞士鞋履、手袋及配饰奢侈品牌
2018/05/18 全球购物
比较基础的php面试题及答案-填空题
2014/04/26 面试题
饲料采购员岗位职责
2013/12/19 职场文书
小学生学习感言
2014/03/10 职场文书
学校消防安全责任书
2014/07/23 职场文书
课外小组活动总结
2014/08/27 职场文书
学习考察心得体会
2014/09/04 职场文书
学校党的群众路线教育实践活动制度建设计划
2014/11/03 职场文书
2015年个人现实表现材料
2014/12/10 职场文书
2015年出纳年终工作总结
2015/05/14 职场文书
趣味运动会广播稿
2015/08/19 职场文书
九年级语文教学反思
2016/03/03 职场文书
MongoDB balancer的使用详解
2021/04/30 MongoDB
Java使用JMeter进行高并发测试
2021/11/23 Java/Android