详解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 相关文章推荐
dojo 之基础篇(二)之从服务器读取数据
Mar 24 Javascript
js使用栈来实现10进制转8进制与取除数及余数
Jun 11 Javascript
JavaScript中获取高度和宽度函数总结
Oct 08 Javascript
浅谈JavaScript中的string拥有方法的原因
Aug 28 Javascript
Bootstrap教程JS插件滚动监听学习笔记分享
May 18 Javascript
JS中如何实现Laravel的route函数详解
Feb 12 Javascript
详解JavaScript调用栈、尾递归和手动优化
Jun 03 Javascript
通过一次报错详细谈谈Point事件
May 17 Javascript
详解Vue中watch对象内属性的方法
Feb 01 Javascript
vue自定义指令实现方法详解
Feb 11 Javascript
ES6中Set和Map数据结构,Map与其它数据结构互相转换操作实例详解
Feb 28 Javascript
微信小程序实现页面分享onShareAppMessage
Aug 12 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
php单例模式示例分享
2015/02/12 PHP
thinkphp3.x中cookie方法的用法分析
2016/05/19 PHP
django中的ajax组件教程详解
2018/10/18 PHP
jquery学习笔记二 实现可编辑的表格
2010/04/09 Javascript
Node.js模块加载详解
2014/08/16 Javascript
js+csss实现的一个带复选框的下拉框
2014/09/29 Javascript
一款基jquery超炫的动画导航菜单可响应单击事件
2014/11/02 Javascript
js HTML5 Ajax实现文件上传进度条功能
2016/02/13 Javascript
Angularjs使用directive自定义指令实现attribute继承的方法详解
2016/08/05 Javascript
Vue.js 递归组件实现树形菜单(实例分享)
2016/12/21 Javascript
underscore之Collections_动力节点Java学院整理
2017/07/10 Javascript
在layui中select更改后生效的方法
2019/09/05 Javascript
layui表单提交到后台自动封装到实体类的方法
2019/09/12 Javascript
JS实现电脑虚拟键盘打字测试
2020/06/24 Javascript
JavaScript 实现拖拽效果组件功能(兼容移动端)
2020/11/11 Javascript
python正则分组的应用
2013/11/10 Python
python实现代码行数统计示例分享
2014/02/10 Python
python图书管理系统
2020/04/05 Python
Python批量提取PDF文件中文本的脚本
2018/03/14 Python
Python做智能家居温湿度报警系统
2018/09/25 Python
Python Pandas实现数据分组求平均值并填充nan的示例
2019/07/04 Python
django settings.py 配置文件及介绍
2019/07/15 Python
python的pstuil模块使用方法总结
2019/07/26 Python
tensorflow模型保存、加载之变量重命名实例
2020/01/21 Python
python 基于opencv实现高斯平滑
2020/12/18 Python
超级英雄、电影和电视、乐队和音乐T恤:Loud Clothing
2019/09/01 全球购物
亚洲在线旅行门户网站:Expedia.com.hk(智游网)
2020/04/14 全球购物
Eclipse面试题
2014/03/22 面试题
运动会通讯稿400字
2014/01/28 职场文书
优秀大学生职业生涯规划书
2014/02/27 职场文书
课程改革实施方案
2014/03/16 职场文书
股权转让协议书
2014/04/12 职场文书
读书小明星事迹材料
2014/05/03 职场文书
社区矫正工作方案
2014/06/04 职场文书
公证委托书
2014/08/01 职场文书
乡镇干部先进性教育活动个人整改措施
2014/09/16 职场文书