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

目录
  • 前言
  • 场景设定
  • 解决方法
    • 注释忽略
    • 场景用例
    • 类型断言
    • 场景用例
    • 泛型转换
    • 场景用例
  • 总结

前言

随着越来越多的前端项目采用 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 报错。

解决方法

注释忽略

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

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

场景用例

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

类型断言

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

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

场景用例

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

  • 第一种写法是给赋值数据下断言,将数据类型强制断言为定义类型,即在上图中,将{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:''
})

场景用例

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

总结

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

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

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

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

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

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

(0)

相关推荐

  • TypeScript类型检查详谈及火爆原因

    目录 让我们先思考一个问题:类型是什么? 动态类型检查 静态类型检查 总结 TypeScript 这些年越来越火,可以说是前端工程师的必备技能了,各大框架都基于它实现. 那么,TypeScript 的出现和爆火是偶然发生的吗?其实不是,类似 TypeScript 这种静态类型语言成为主流是必然会发生的.为什么这么说呢? 让我们先思考一个问题:类型是什么? 类型具体点来说就是指 number.boolean.string 等基础类型和 Object.Function 等复合类型,它们是编程语言提供

  • 直观详细的typescript隐式类型转换图文详解

    正文 1.unknown是所有类型的父类型,其他类型都可以赋值给 unknown let a: undefined = undefined; let b: null = null; let x2: unknown; x2 = a; //正确 x2 = b; //正确 2.never 是任何类型的子类型,可以赋给任何类型 let a: undefined = undefined; let b: null = null; function err(): never { // OK throw new

  • TypeScript新语法之infer extends示例详解

    目录 正文 模式匹配 提取枚举的值的类型 总结 正文 我们知道,TypeScript 支持 infer 来提取类型的一部分,通过模式匹配的方式. 模式匹配 比如元组类型提取最后一个元素的类型: type Last<Arr extends unknown[]> = Arr extends [...infer rest,infer Ele] ? Ele : never; 比如函数提取返回值类型: type GetReturnType<Func extends Function> = F

  • TypeScript 的条件类型使用示例详解

    目录 TypeScript 的条件类型使用方式 条件类型和 keyof 组合 在条件返回中使用 T 在类型输出中使用 T 时的联合类型 使用条件类型推断类型 总结 TypeScript 的条件类型使用方式 我们可以使用 TypeScript 中的条件类型来根据逻辑定义某些类型,就像是在编写代码那样. 它采用的语法和我们在 JavaScript 中熟悉的三元运算符很像:condition ? ifConditionTrue : ifConditionFalse. 我们来看看他是怎么工作的. 假设我

  • TypeScript编写自动创建长度固定数组的类型工具详解

    目录 前言 代码 判断 List 的长度是否等于 Len 前言 在 TypeScript 中,当需要一个长度固定的数组时,通常会想到使用元组来进行表示,不过相对于数组而言,元组的每个元素的类型都不必是一致的. 如果现在需要一个长度为 30,元素类型为 string 的数组类型,其实就是一个元组,如果直接手写出来,那也太麻烦了,本文因此有感而发,编写了自动创建的类型工具. 代码 首先,不管三七二十一,先把这个类型工具给定义出来: type FixedArray = any 然后开始逐步分析,先从泛

  • TypeScript中extends的正确打开方式详解

    目录 前言 extends第一式:继承 类继承类 接口继承接口 接口继承类 extends第二式:三元表达式条件判断 普通的三元表达式条件判断 情况一:Type1和Type2为同一种类型. 情况二:Type1是Type2的子类型. 情况三: Type2类型兼容类型Type1. 带有泛型的三元表达式条件判断 extends第三式:泛型约束 前言 最近完整地看了一遍TypeScript的官方文档,发现文档中有一些知识点没有专门讲解到,或者是讲解了但却十分难以理解,因此就有了这一系列的文章,我将对没有

  • TypeScript 泛型推断实现示例详解

    目录 前言 基础类型准备 最终使用的方式 基于Interface的实现 (失败了) 所有内容都基于type 实现 完整Demo 结束语 前言 最近做东西都在用ts,有时候写比较复杂的功能,如果不熟悉,类型写起来还是挺麻烦的.有这样一个功能,在这里,我们就不以我们现有的业务来举例了,我们还是已Animal举例,来说明场景.通过一个工厂来创建不同的动物实例.在这里我们借助泛型来实现类型的约束和动态推到指定类型. 基础类型准备 用一个枚举来定义Animal的类型 enum EAnimalType {

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

    目录 前言 场景设定 解决方法 注释忽略 场景用例 类型断言 场景用例 泛型转换 场景用例 总结 前言 随着越来越多的前端项目采用 typescript 来开发,越来越多前端开发者会接触.使用这门语言.它是前端项目工程化的一个重要帮手,结合 vscode 编辑器,给予了前端开发者更严谨.高效的编码体验.但同时,严格的类型检查也会使部分开发者的编码效率有所降低,将时间花费在解决类型冲突.类型不匹配上,从而导致望而却步,迟迟不敢上手. 本文描述了几种绕过 typescript 类型检查的方法,帮助t

  • 详解vite2.0配置学习(typescript版本)

    介绍 尤于溪的原话. vite与 Vue CLI 类似,vite 也是一个提供基本项目脚手架和开发服务器的构建工具. vite基于浏览器原生ES imports的开发服务器.跳过打包这个概念,服务端按需编译返回. vite速度比webpack快10+倍,支持热跟新, 但是出于处于测试阶段. 配置文件也支持热跟新!!! 创建 执行npm init @vitejs/app ,我这里选择的是vue-ts 版本 "vite": "^2.0.0-beta.48" alias别

  • 详解Vue开发网站seo优化方法

    因为用了vue等js的数据绑定机制来展示页面数据,爬虫获取到的html是模型页面而不是最终数据的渲染页面,搜索引擎是不回去执行请求到的js.vue的项目都是ajax请求数据,引擎爬虫进入页面获取不到文字内容,现在大多数解决方案是不采用ajax渲染数据,而是采用server端渲染,也就是所谓的SSR. 目前基于vue的方案是Nuxt.js,同类型的也有React版的Nuxt.js所以服务端渲染就是尽量在服务器发送到浏览器前,页面上是有数据可让爬虫进行爬取 方法一.利用prerender-spa-p

  • 详解Flask开发技巧之异常处理

    目录 一.Flask内置异常处理 二.HTTPException类分析 三.自定义异常处理类 四.方便的定义自己的错误类 五.注意事项 一.Flask内置异常处理 要想在Flask中处理好异常,有一套自己的异常处理机制,首先,我们必须先知道Flask自己是如何处理异常的.去flask的源码里找一找会发现,在flask源码的app.py文件下,有很多会抛出异常的方法,其中拿一个举例: def handle_exception(self, e): """Default excep

  • 详解如何实现一个Kotlin函数类型

    目录 接口与函数类型 总结 接口与函数类型 业务开发中,经常会有实现一个函数式接口(即接口只有一个方法需要实现)的场景,大家应该都会不假思索的写出如下代码: interface Callback { fun response(): String } class Achieve: Callback { override fun response(): String { return "" } } 这么写当然没什么毛病,甚至为了让kotlin支持对接口Callback的SAM转换,你还可以

  • 详解Python开发语言中的基本数据类型

    目录 1.Python的基本数据类型 2.整数类型的概念以及使用 2.1.整数类型的概念 2.2.使用Python操作整数类型 3.浮点数类型的概念以及使用 4.布尔类型的概念以及使用 1.Python的基本数据类型 数据类型想必大家都知道是什么含义,指的是输入数据的类型,任何数据都有明确的数据类型,例如我们输入100,这个数据就是整数类型,输入7.7这个数据就是浮点数类型,输入字母.汉字.字母加汉字的数据都是字符串类型. Python基本数据类型有三种: 整数类型:数字 浮点数类型:带小数点的

  • 详解IOS开发中生成推送的pem文件

    详解IOS开发中生成推送的pem文件 具体步骤如下: 首先,需要一个pem的证书,该证书需要与开发时签名用的一致. 具体生成pem证书方法如下: 1. 登录到 iPhone Developer Connection Portal(http://developer.apple.com/iphone/manage/overview/index.action )并点击 App IDs 2. 创建一个不使用通配符的 App ID .通配符 ID 不能用于推送通知服务.例如,  com.itotem.ip

  • 详解JavaScript中的4种类型识别方法

    具体内容如下: 1.typeof [输出]首字母小写的字符串形式 [功能] [a]可以识别标准类型(将Null识别为object) [b]不能识别具体的对象类型(Function除外) [实例] console.log(typeof "jerry");//"string" console.log(typeof 12);//"number" console.log(typeof true);//"boolean" console

  • 详解微信开发中snsapi_base和snsapi_userinfo及静默授权的实现

    详解微信开发中snsapi_base和snsapi_userinfo及静默授权的实现 snsapi_base与snsapi_userinfo属于微信网页授权获取用户信息的两种作用域 snsapi_base只能获取access_token和openID snsapi_userinfo可以获取更详细的用户资料,比如头像.昵称.性别等 首先,这里的access_token与基础access_token(比如自定义菜单用到的)是不一样的.两者区别如下: 网页授权的access_token在每次获取ope

  • 详解golang开发中http请求redirect的问题

    这两天在开发项目的时候遇到了一个问题,请求了一个URL,它会302到另一个地址,本意上只是想检查这个URL是否会做3XX的redirect跳转,结果每次reqeust都会返回最后一跳的结果.后来就看了下源码,了解下请求跳转的机制 实现代码 看下实现的简单代码 func main() { client := &http.Client{} url := "http://www.qq.com" reqest, err := http.NewRequest("GET"

随机推荐