六、枚举
1、普通枚举
枚举常使用于我们在程序中需要做权限管理或者做判断时等各种场景。枚举比较简单,下面直接用代码演示:
enum Direction{ Up, Down, Left, Right } console.log(Direction.Up) //0 console.log(Direction.Down) //1 console.log(Direction.Left) //2 console.log(Direction.Right) //3 console.log(Direction[0]) //Up 复制代码
除了以上基本用法外,我们还可以给枚举赋值:
enum Direction{ Up = 10, Down, Left, Right } console.log(Direction.Up) //10 复制代码
2、常量枚举
我们来定义一个常量,与 enum
做判断。
enum Direction{ Up = 'Up', Down = 'Down', Left = 'Left', Right = 'Right' } //定义一个常量,直接与enum做判断 const value = 'Up'; if(value === Direction.Up){ console.log('go Up!') // go Up! } 复制代码
使用常量枚举可以有效地提升性能,常量会内联枚举的任何用法,而不会把枚举变成任意的 Javascript
代码。
这样一说,那是不是所有的 enum
都可以使用常量枚举呢?答案自然是否定的。
枚举的值有两种类型,一种是常量值枚举(constant),一种是计算值枚举(computed)。只有常量值枚举可以进行常量枚举,而计算值枚举不能进行常量枚举。
七、泛型
接下来我们来讲 TypeScript
中最难的一部分,泛型。
1、普通泛型
泛型,即 generics
。指在定义函数、接口或类的时候,我们不预先指定类型,而是在使用的时候再指定类型和其特征。
可以理解为,泛型就相当于一个占位符或者是一个变量,在使用时再动态的填入进去,填进去以后既可以来确定我们的类型值。
接下来我们用代码来演示一下:
function echo<T>(arg: T): T{ return arg } const result = echo(true) console.log(result) // true 复制代码
我们通过 <>
来定义一个未知的泛型,之后当我们给它赋值时,就可以对应值的数据类型。
现在我们再用泛型来定义一个 number
类型的数组。具体代码如下:
// 早期定义一个number类型的数组 let arr: number[] = [1, 2, 3] // 用泛型定义一个number类型的数组 let arrTwo: Array<number> = [1, 2, 3] 复制代码
假如我们现在要调换两个元素的位置,那么用泛型我们可以这么实现。具体代码如下:
function swap<T, U>(tuple: [T, U]): [U, T]{ return [tuple[1], tuple[0]] } const result2 = swap(['abc', 123]) console.log(result2[0]) //123 console.log(result2[1]) //abc 复制代码
通过泛型,我们就顺利调换了两个元素的位置。
2、约束泛型
在泛型中使用 extends
关键字,就可以让传入值满足我们特定的约束条件,而不是毫无理由的随意传入。
比如,我们想要让我们定义的内容是一个数组,我们可以这么处理。具体代码如下:
function echoWithArr<T>(arg: T[]): T[]{ console.log(arg.length) return arg } const arrs = echoWithArr([1, 2, 3]) 复制代码
这样,就把 arrs
定义为一个数组。
假设我们现在想要让我们定义的内容可以访问到 length
方法,那么我们需要加一点佐料。具体代码如下:
interface IWithLength{ length: number } function echoWithLength<T extends IWithLength>(arg: T): T{ console.log(arg.length) return arg } const str = echoWithLength('str') const obj = echoWithLength({ length: 10, width: 20 }) const arr2 = echoWithLength([1, 2, 3]) 复制代码
通过 extends
关键字来继承特定的 interface
,使得我们定义的内容 str
, obj
,arr2
达到可以访问length方法的目的。
通过以上举例,我们可以知道,泛型可以用来灵活的约束参数的类型,参数不需要是个特别死板的类型,而可以通过我们的约束来达到我们想要的目的。
3、泛型在类和接口中的使用
(1)泛型在类中的使用
class Queue<T>{ private data = [] push(item: T){ return this.data.push(item) } pop(): T{ return this.data.shift() } } // 确定这是一个number类型的队列 const queue = new Queue<number>() queue.push(1) console.log(queue.pop().toFixed()) 复制代码
(2)泛型在接口中的使用
interface KeyPair<T, U>{ key: T value: U } let kp1: KeyPair<number, string> = {key: 1, value: 'str'} let kp2: KeyPair<string, number> = {key: 'str', value: 2} 复制代码
通过以上代码演示可以发现,泛型就像是创建了一个拥有特定类型的容器,就仿佛给一个容器贴上标签一样。
八、类型别名
1、类型别名
类型别名,即 type aliase
。类型别名可以看作是一个快捷方式,可以把一个写起来很繁琐的类型创建一个简单的写法。比如:
//用以下这种写法,每次都要写一长串的(x: number, y: number) => number let sum: (x: number, y: number) => number const result = sum(1, 2) //用type给类型进行别名 type PlusType = (x: number, y: number) => number let sum2: PlusType const result2 = sum2(2, 3) //一个类型可以是字符串也可以是数字 type StrOrNumber = string | number let result3: StrOrNumber = '123' result3 = 123 复制代码
2、字符串字面量
字符串字面量,指可以提供一系列非常方便使用的常量写法。比如:
const str: 'name' = 'name' const number: 1 = 1 type Direction = 'Up' | 'Down' | 'Left' | 'Right' let toWhere: Direction = 'Left' 复制代码
3、交叉类型
交叉类型,使用 type
这个扩展对象的一种方式。比如:
interface IName{ name: string } type IPerson = IName & {age: number} let person: IPerson = {name: 'monday', age: 18} 复制代码
九、声明文件
我们在写ts时,难免会有遇到要引入第三方库的时候。这个时候就需要ts来做特殊处理。主要有以下两种做法:
1、 .d.ts 文件引入
假设我们要引入JQuery库来使用,那么我们可以在外部新增一个 JQuery.d.ts
文件,文件内代码如下:
declare var JQuery: (selector: string) => any; 复制代码
之后便可以在我们定义的 ts
文件下引用 JQuery
相关库的内容。比如:
jQuery('#foo') 复制代码
2、npm安装
我们也可以安装对应的第三方库的 npm
包。假如我们现在要引入一个 JQuery
库,那么我们可以这么处理。
npm install --save @type/jquery 复制代码
十、内置类型
我们在写 ts
代码时,其实不知不觉已经使用了很多的内置对象。对象呢,是指根据标准(标准指 ECMA
、 DOM
等标准),在全局作用域 global
上面存在的对象。那我们在运行 tsc
时,这些内置的对象就会被当作附加的礼物给程序加载进行。接下来我们来体会一下几种常见的内置对象。
全局对象:
// global object 全局对象 const a: Array<number> = [1, 2, 3] const date = new Date() date.getTime() const reg = /abc/ reg.test('abc') 复制代码
内置对象:
// build-in object 内置对象 Math.pow(2, 2) 复制代码
DOM和BOM对象:
// DOM 和 BOM let body = document.body let allLis = document.querySelectorAll('li') allLis.keys() document.addEventListener('click', e => { e.preventDefault() }) 复制代码
功能性类型:
// Utility Types 功能性类型 interface IPerson{ name: string age: number } let monday: IPerson = {name: 'monday', age: 20} //可选属性 type IPartial = Partial<IPerson> let monday2: Ipartial = {name: 'monday'} //移除某一个属性 type Omit = Omit<IPerson, 'name'> let monday3: Omit = {age: 20} 复制代码
十一、结束语
关于 ts
的入门讲到这里就结束啦!希望大家能对 ts
有一个简单的认识!