详解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 相关文章推荐
一个网马的tips实现分析
Nov 28 Javascript
JQuery入门——移除绑定事件unbind方法概述及应用
Feb 05 Javascript
javascript删除数组重复元素的方法汇总
Jun 24 Javascript
关于获取DIV内部内容报错的原因分析及解决办法
Jan 29 Javascript
理解Javascript图片预加载
Feb 23 Javascript
JavaScript模块详解
Dec 18 Javascript
详解Webpack实战之构建 Electron 应用
Dec 25 Javascript
浅析Vue实例以及生命周期
Aug 14 Javascript
微信小程序Getuserinfo解决方案图解
Aug 24 Javascript
JavaScript变量作用域及内存问题实例分析
Jun 10 Javascript
JavaScript组合模式---引入案例分析
May 23 Javascript
Vue+TypeScript中处理computed方式
Apr 02 Vue.js
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
php header功能的使用
2013/10/28 PHP
PHP中shuffle数组值随便排序函数用法
2014/11/21 PHP
PHP中empty和isset对于参数结构的判断及empty()和isset()的区别
2015/11/15 PHP
PHP简单获取随机数的常用方法小结
2017/06/07 PHP
IE中radio 或checkbox的checked属性初始状态下不能选中显示问题
2009/07/25 Javascript
jQueryUI如何自定义组件实现代码
2010/11/14 Javascript
简单的jquery拖拽排序效果实现代码
2011/09/20 Javascript
用按钮控制iframe显示的网页实现方法
2013/02/04 Javascript
jQuery基本选择器选择元素使用介绍
2013/04/18 Javascript
jQuery动态添加删除select项(实现代码)
2013/09/03 Javascript
JavaScript之IE的fireEvent方法详细解析
2013/11/20 Javascript
JS获取月的最后一天与JS得到一个月份最大天数的实例代码
2013/12/16 Javascript
JavaScript中实现最高效的数组乱序方法
2014/10/11 Javascript
jQuery实现TAB选项卡切换特效简单演示
2016/03/04 Javascript
详解JavaScript的另类写法
2016/04/11 Javascript
简洁实用的BootStrap jQuery手风琴插件
2016/08/31 Javascript
微信小程序 动态的设置图片的高度和宽度详解及实例代码
2017/02/24 Javascript
js实现图片加载淡入淡出效果
2017/04/07 Javascript
[00:31]2016完美“圣”典风云人物:国士无双宣传片
2016/12/04 DOTA
Python Web框架Pylons中使用MongoDB的例子
2013/12/03 Python
Linux下编译安装MySQL-Python教程
2015/02/02 Python
python遍历一个目录,输出所有的文件名的实例
2018/04/23 Python
python实现超市扫码仪计费
2018/05/30 Python
python中使用iterrows()对dataframe进行遍历的实例
2018/06/09 Python
200行python代码实现2048游戏
2019/07/17 Python
解决Atom安装Hydrogen无法运行python3的问题
2019/08/28 Python
在python中利用dict转json按输入顺序输出内容方式
2020/02/27 Python
Django DRF APIView源码运行流程详解
2020/08/17 Python
html5+css3气泡组件的实现
2014/11/21 HTML / CSS
Monica Vinader官网:英国轻奢珠宝品牌
2020/02/05 全球购物
城市规划毕业生求职信
2013/10/10 职场文书
财务方面个人工作的自我评价
2013/12/28 职场文书
师范学院教师自荐书
2014/01/31 职场文书
《假如》教学反思
2016/02/17 职场文书
python中的class_static的@classmethod的巧妙用法
2021/06/22 Python
MySQL 用 limit 为什么会影响性能
2021/09/15 MySQL