美文网首页JavaScript学习我爱编程知识
Typescript 是如何保证前端质量的

Typescript 是如何保证前端质量的

作者: 275cafb52764 | 来源:发表于2017-06-08 11:09 被阅读2783次

    | 导语Typescript 作为 Javascript 的超集,为 Javascript 赋予了数据强类型特性,尽管 Javascript 作为动态开发语言具备开发效率高的特点,但是成也萧何败也萧何,隐式类型转换同时带来了大量不可预知的类型错误,而 Typescript 通过强类型约束有效地解决了这点。

    Typescript 是微软于 2014 年发布的基于 Javascript 的超集,和 Babel 将 ES6 语法编译成 ES5 一样,Typescript 也会把 TS 的语法编译成从各种目标代码(一会儿继续说这事儿)。

    开发目标

    我们很清楚 ES6 只是 ES5 的扩展,尽管 Chrome 等浏览器已经率先实现了部分 ES6 功能,但依然需要通过 Babel 进行编译,才能对旧版的浏览器提供支持,其实我个人觉得它除了解决部分开发效率,对于 Javascript 弱类型的实质没有任何改进,从产品质量保证而言,Babel 提供了编译时的语法检查,但是能力仅限于检查未定义变量,而浏览器中直接运行的 ES6 语法,和 Javascript 一样是纯粹的动态语言,最基本的检查能力都不具备。

    回到 2014 年,那是个 ES6 语法还未成型的年代,当时有句话叫做“动态语言一时爽,重构时候火葬场”,各大厂商已经认识到了 Javascript 的动态特性无法支撑大型项目的开发,纷纷提出了自己的解决方案,例如Google DartFacebook flow.js以及本文要介绍的Microsoft Typescript

    笔者认为,Typescript 是最合适的解决方案,它很简单地为 Javascript 赋予了单个对象赋予了类型、对象赋予了 interface、为目前现有的 Javascript 库赋予了 Declaration File 使他们全部都获得了静态的类型系统,与 ES6 语法基本兼容,比重新设计整个语言的 Dart 更轻,但比 flow.js 更重,配合官方免费的、跨平台的VisualStudio Code更是将整个开发生态打造得无可挑剔(另外说一句这个编辑器也是 Typescript 开发,基于 Electron 的 Web 应用)。

    一个简单的范例

    我们可以通过tnpm install -g ts-node来体验 typescript,范例代码是一个很常见的场景,做数据运算的时候,经常会有数据类型不对的情况,Typescript 对于直接的数据操作并没有类型检查,但当生成一个函数,并且对参数赋予类型时,便会在编译时进行类型检查,对于不符合类型要求的地方,会直接抛出错误,中止编译过程,同时我们还可以看到,它对 Javascript 内置的函数都已经做了基本的类型声明,parseInt(value)后会是一个 number,符合了函数的入参类型要求,便正确输出返回值。

    是否有一种 Java 的既视感?通过静态类型声明,就具备了和 Java 一样的开发大型应用的能力,

    基本配置

    Typescript 比较好的地方是,编译器本身只有typescript一个包,通过tnpm install -g typscript将会安装 v2.0.10 稳定版(截止发稿时),安装之后,系统中将会多出一个tsc命令,它是 Typescript 的编译器。

    可以写一个很简单的代码,进行编译测试。

    letvalue:string;value='Hello world';constprintStr = (str:string) => {  console.log(str);}printStr(value);

    保存为helloworld.ts,然后直接执行tsc helloworld.ts,将会输出成默认的 ES3 javascript

    varvalue;value ='Hello world';varprintStr =function(str){console.log(str);};printStr(value);

    Typescript 是具备直接输出 ES6 能力的,只需要在编译时加上-t es6参数,便可以输出 ES6 的目标文件,从输出的 js 文件和 ts 文件对比,就会发现 ts 只是比 js 多了个参数类型定义。

    letvalue;value='Hello world';constprintStr = (str) => {  console.log(str);};printStr(value);

    编译参数可以直接在命令行后面加上,更多参数可以参考编译选项,也可以通过tsconfig.json直接定义,首先可以使用tsc --init生成初始化的配置文件,我这里加了files用于定义输入的源代码。

    {"compilerOptions": {"module":"commonjs","target":"es5","noImplicitAny":false,"sourceMap":false},"files": ["helloworld.ts"]}

    然后直接使用tsc就可以进行编译了,更多编译参数,请参考tsconfig.json 文档

    需要特别说明的是以下几个参数

    参数名称可选值说明

    targetES3、ES5、ES2015输出的 Javascript 代码类型,默认是 ES3,如果只兼容到 IE9 以上,用 ES5 即可,Typescript 生成的代码质量已经很高了,以前还需要用 Babel 做后端再二次编译一次,现在完全无需 Babel。

    modulenone、commonjs 、amd 、system、umd 、es2015输出的模块系统,可以看到支持得很全面,最新式的 system.js 也支持到了,需要说明的是,有一个--outFile参数可以讲所有代码打包成一个文件(可以代替 webpack),但是当使用它打包时,只能使用amd或者system这种支持异步加载的模块类型。

    jsxReact、Preserve处理 jsx 的方案、React可以讲所有 jsx 编译成 React.createElement 的形式,Preserve则保留原有格式

    配合 webpack

    Typescript + Webpack 使用非常简单,和 Babel 非常类似,只需要加上ts-loader或者awesome-typescript-loader这两个 loader 各有千秋,其实目前 Typescript 直出 ES5 已经非常成熟,用 ts-loader 即可,如果有需要使用 Babel 进行 ES6 到 ES3 编译的可以使用 awesome-typescript-loader 据说有更好的性能和特性。

    这里有一份webpack 范例配置文件

    语法 Linter

    Linter 的作用是保证多人开发时的语法的一致性,它可以在编译前进行语法检查,找出不合规的地方,并给出 Warning,这些不合规的地方未必会影响代码运行结果,但是当多人开发时,保持一致的代码风格还是很有必要的。

    和 Javascript 一样,Typescript 也有 linter,叫做tslint,它提供了语法检查和开发指导。

    使用tnpm install -g tslint之后,会增加tslint命令,可以使用tslint --init生成 tslint 的默认配置文件,我们用它来检查一下刚出的helloworld.ts。

    » tslint helloworld.ts helloworld.ts[2,9]:' should be "helloworld.ts[5,2]: Missing semicolon

    很明显,它提示了第二行的单引号需要改为双引号,同时第五行少了一个分号。

    实际开发之中是不会使用默认的宽松配置的,tslint 已经提供了大量参考配置,我们一般使用“推荐”配置,可以参考tslint.json它从代码的考虑已经做了大量优化,可以作为项目中的推荐方案。

    语法简介

    Typescript 语法与 ES6 语法基本一致,const、let 箭头函数可以直接使用,比较出色的地方是它不需要增加插件便可以实现一些高级语法编译,例如 async 和 await,相对于 Babel 我感觉 Typescript 编译出的代码更佳简单干净,可读性高。

    和 ES6 不一样的地方,是它增加了类型系统,这又主要分以下几种类型定义方式。

    变量类型系统

    在 Typescript 中,声明变量时如果直接赋值,则会使用自动类型判断固定该变量的类型,例如:

    constfoo =123;// numberconstbar ='abc';// string

    如果需要声明一个变量,但不赋值,就必须给它声明一个类型,当后期使用类型不符合时会抛出错误。

    letfoo:number;foo =123;//Okfoo ='abc';//Type'string'isnotassignable to type'number'. (2322)

    Typescript 的基本类型主要有:

    类型范例说明

    booleanlet isDone: boolean = false;布尔值,只允许 true、false

    numberlet decimal: number = 6;数字类型,包含正数、浮点数和16进制数

    stringlet color: string = “blue”;字符串

    Arraylet list: number[] = [1, 2, 3];数组,需要说明的是数据也需要声明内容的类型,写法就是内容类型加上[]

    Tuplelet x: [string, number];强制数组内的元素类型

    Enumenum Color {Red, Green, Blue};枚举类型

    Anylet notSure: any = 4;不限制变量类型,如果使用它就是普通的 JS,应该去声明每一个变量的类型,避免使用 any。

    Voidlet unusable: void = undefined;空值,只允许赋予 null 和 undefined

    Null and Undefinedlet u: undefined = undefined;比 void 更佳详细,null 或者 undefined 只可选其一

    Never主要用于声明一个无返回值的函数

    更多范例,请参考官方基础类型文档。

    对象 Object

    对于 Object 的类型定义,主要通过interface关键字进行定义,和基本变量定义类似,interface也非常简单。

    interface IHelloWorld {hello: string;  world: number;  foobar?:void;// Optional property}consthelloWorld: IHelloWorld {hello:'Hello',world:123,}console.log(JSON.stringify(helloWorld));helloWorld.foobar =null;console.log(JSON.stringify(helloWorld));helloWorld.test =123;console.log(JSON.stringify(helloWorld));

    直接使用 ts-node 运行会发现编译不过,抛出了错误

    test.ts(17,12): error TS2339: Property'test'doesnotexistontype'IHelloWorld'.

    是因为在最后我们给 helloWorld 赋予了一个 interfaceIHelloWorld中不存在的testproperty,把它删掉就可以正常编译运行了,由此可见 Typescript 的严谨。

    类 property 类型声明、方法私有性声明

    和 ES6 一样,Typescript 也提供了class关键字用于声明累,而 property 类型声明借鉴了初始化值的语法,直接在constructor()之上,像初始化变量一样进行类型赋予即可。

    classFoobar{privatestr:string;// this.str typepublicconstructor(str){this.str = str;  }publicprintStr(){    console.log(this.str);  }}constfoo =newFoobar('Hello world');foo.printStr();

    这里还能对方法的私有性进行定义,当不慎掉用到private方法时,编译器就会报出错误阻止编译过程,有效保护私有方法。

    第三方库接口类型定义 Declaration File

    Typescript 因为其特点,所以对第三方库提供的接口也有强类型的需求,但是老的第三方库往往都是使用 Javascript 进行开发,并没有声明接口类型,微软采用了一个取巧的办法,给第三方库增加了一个.d.ts的类型声明文件。

    社区里已经有了绝大多数常用库的类型声明文件,保存在DefinitelyTyped仓库里,可以直接使用tnpm的@typesprivate repo 进行安装,例如tnpm install@types/react-bootstrap安装 react-bootstrap

    类型声明文件还有一个好处是它在声明类型的同时,还可以对函数的用法进行说明,这样开发起来不用查看源代码或者官方文档,在 IDE 里就能了解方法的功能。

    但遇到比较冷门的第三方库,没有d.ts文件提供时,直接import它会提示找不到 module,对于比较小的第三方库,建议自己用 Typescript 重写,也可以自己开发d.ts文件进行类型定义,Typescript 2.0 对d.ts文件进行了大量简化,具体开发内容有点大,可以参考官方文档,未来或许会单独写一篇《Typescript Declaration File 开发指南》。

    成功案例

    因为 Typescript 静态类型的特性,各大公司都在积极使用 Typescript 进行项目开发。

    Google 的Angular 2

    蚂蚁金服的Ant.design

    Teambition

    目前我们组已经在内部使用 Typescript 进行项目开发,目前主要成果有:

    vincenzheng 的微信小程序脚手架

    xqkuang 的react-redux 脚手架

    xqkuang 的NodeJS 服务器框架(进行中)

    xqkuang 的腾讯指数统计埋点

    温馨提醒:

    1、微信端搜索课程

    在“腾讯课堂”官方微信里,回复你想学习的内容,即可快速找到你期待的课程哦!

    2、学习方式

    【电脑端】

    *可通过登录ke.qq.com进入学习;

    *可通过windows PC版QQ客户端面板上的课堂入口进入学习。

    【移动端】

    *下载APP “腾讯课堂” 即可进入学习;

    *关注微信公众号或者手Q公众号“腾讯课堂”,进入学习。

    (注:微信和QQ的课程报名信息独立,登录时请选择对应的登录方式)

    相关文章

      网友评论

      • spanman:react 的脚手架用不了了

      本文标题:Typescript 是如何保证前端质量的

      本文链接:https://www.haomeiwen.com/subject/avbzfxtx.html