前言
最近工作一直很忙,复盘周期也有所拉长,不过还是会坚持每周复盘。今天笔者将复盘一下typescript在前端项目中的应用,至于为什么要学习typescript,我想大家也不言自明,目前主流框架vue和react以及相关生态的内部构建大部分都采用了typescript,其原因就在于它的静态类型检查极大的提高了代码的可读性和可维护性,而且定位问题非常方便。下面上一份关于typescript的官方定义,方便大家理解:
概要
任何语言的学习都要有学习和思考体系,前端也不例外,笔者将按照如下图所示结构来进行讲解:
正文
我们目前项目开发用的最多的就是webpack,对于ts,我们也很方便的可以通过ts-loader对其进行编译配置,为了降低大家学习ts的难度,笔者推荐采用vue-cli3或者umi直接搭建ts项目,这样可以更快的上手ts开发。
核心知识点
TypeScript支持与JavaScript几乎相同的数据类型,此外还提供了实用的枚举类型方便我们使用。接下来我们简单介绍一下这几种类型的用法.
以上是typescript中常用的几种类型, 也是我们必须掌握的基本知识. 这里值得补充的是typescript的类型断言, 也是解决ts警告的利器,比如我们确切的知道某种数据的数据类型,我们可以这么做:
TypeScript的核心原则之一是对值所具有的结构进行类型检查。 在TypeScript里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。接下来我们看看如何定义和使用接口(Interface):
类型检查器不会去检查属性的顺序,只要相应的属性存在并且类型也是对的就可以。其次我们还可以定义可选属性和只读属性. 可选属性表示了接口里的某些属性不是必需的,所以可以定义也可以不定义.可读属性使得接口中的某些属性只能读取而不能赋值. 具体案例如下:
在实际场景中, 我们往往还会遇到不确定属性名和属性值类型的情况, 这种情况往往发生在第三发SDK接入或者后端响应中, 这个时候我们可以利用索引签名来设置额外的属性和类型, 案例如下:
接口除了描述带有属性的普通对象外,也可以描述函数类型。我们需要给接口定义一个调用签名, 参数列表里的每个参数都需要名字和类型。案例如下:
我们在vue和react开发中,也会经常使用class这种类来编写可复用组件和库, 既然ts可以描述函数类型, 那么是不是也可以用来描述类类型呢? 答案是可以的.但是类接口的定义稍微有点复杂, 我们都知道类是具有两个类型的:静态部分的类型和实例的类型. 当一个类实现了一个接口时,只对其实例部分进行类型检查。constructor存在于类的静态部分,所以不在检查的范围内。. 这句话相当关键, 我们在定义类接口的时候也要主要这一特点, 案例如下:
关于类接口的话题我们在上文已经介绍了, 这里我们来具体了解一下类. 和js的class一致, typescript的类有公共,私有与受保护的修饰符. 具体含义如下:
函数类型在上文已经介绍过了, 这里主要在讲一下可选参数这个概念. JavaScript里每个参数都是可选的,可传可不传。没传参的时候其值就是undefined。在TypeScript里我们可以在参数名旁使用 ?实现可选参数的功能。具体案例如下:
我们可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。这样用户就可以以自己的数据类型来使用组件。泛型是typescript中比较难懂的知识点, 但是非常重要, 几乎任何第三方组件库里都会用到. 我们先来看个最简单的例子:
我们给iSay添加了类型变量T。T帮助我们捕获用户传入的类型(比如:string),这样我们就可以使用这个类型。之后我们再次使用T当做返回值类型。现在我们可以知道参数类型与返回值类型是相同的了。这允许我们跟踪函数里使用的类型的信息。
我们还可以把泛型变量T当做类型的一部分使用,而不是整个类型, 这样可以增加我们的使用灵活性, 案例如下:
类似于函数类型的定义, 我们也可以定义泛型接口, 并且可以把泛型参数当作整个接口的一个参数, 这样我们就能清楚的知道使用的具体是哪个泛型类型. 案例代码如下:
同样的我们还可以定义泛型类.我们只需要使用(<>)括起泛型类型,跟在类名后面即可. 具体案例如下:
typescript的高级类型里我们主要讲解如下核心知识点:
我们通过字符 & 来表示联合, 此时以上代码中的返回值会具有T和U的类型.
联合类型表示一个值可以是几种类型之一。我们用竖线(|)分隔每个类型,所以 number | string | boolean表示一个值可以是 number, string,或 boolean。具体例子如下:
值得注意的是: 如果一个值是联合类型,我们只能访问此联合类型的所有类型里共有的成员。
还有一种常见的需求是, 我们在实现自己的类后,需要支持类方法的链式调用, 这个时候我们应该返回this, 在typescript中我们就需要了解多态的 this类型. 它表示的是某个包含类或接口的子类型。这被称做 F-bounded多态性。要想在typescript中支持链式, 我们可以这么写:
下面一个我们需要知道的知识点是索引类型查询操作符. 一般用keyof表示。对于任何类型T, keyof T的结果为T上已知的公共属性名的联合。比如我们定义一个接口Animal:
keyof Animal是完全可以与 'cat' | 'dog'互相替换的。不同的是如果我们添加了其它的属性到 Animal,例如 pig: string,那么 keyof Animal会自动变为 'cat' | 'dog' | 'pig'。
命名空间主要作用是用来组织代码,以便于在记录它们类型的同时还不用担心与其它对象产生命名冲突。由于命名空间的用法很简单,这里我们以网上比较流行的D3作为例子, 代码如下:
在熟悉以上基础知识之后, 我们看一下如何使用支持typescript的第三方类库. 比如说我们常用的lodash, 那么正确的使用步骤如下:
声明文件也是一个非常重要的知识点.对于使用未经声明的全局函数或者全局变量, typescript往往会报错, 所以我们可以在对应位置添加xxx.d.ts文件, 并在里面声明我们所需要的变量, ts会自动检索到该文件并进行解析. 以下是几个案例, 供大家参考学习:
React + Typescript项目实战
为了帮助大家快速上手typescript开发, 这里我们采用umi来搭建一个支持ts的项目, 不熟悉的朋友可以参考笔者之前学习umi的文章.
我们在项目src目录下创建一个global.d.ts来作为我们全局的声明文件, 用来处理全局声明和兼容第三方库.
我们在src目录下创建一个utils目录用来存放我们的工具类或者通用库, 比如在utils下新建一个tool.ts作为我们的通用工具函数, 这里我们写个最简单的例子:
最后
如果想学习更多H5游戏, webpack,node,gulp,css3,javascript,nodeJS,canvas数据可视化等前端知识和实战,欢迎在公号《趣谈前端》加入我们的技术群一起学习讨论,共同探索前端的边界。
本文分享自微信公众号 - 趣谈前端(beautifulFront)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。