typescript学习笔记——泛型和枚举

2019 / 06 / 08

泛型(generics)

泛型是大多数前端开发者几乎没有听过的一种概念,可以看维基百科或者菜鸟教程里对泛型的解释

说的直白些,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。

参数化类型?给数据类型指定一个参数,类型和参数有什么关系?大多数没有系统的使用ts的童鞋看到这里肯定是一脸懵逼的。

ok,首先看一个简单的需求

需要编写一个函数,接受一个参数,返回这个只包含这个参数一个元素的数组,大概意思就是这样

参数 => [参数]

根据需求完美的写出了这个函数的第一版。

function arrayify(arg: any): any[] {
return [arg]
}

但是问题来了,期望的是输入一个数值,返回一个数组的数组,但是无法知道any[]是个什么类型的数组。而使用泛型就能很好的解决这个问题。

function arrayify<T>(arg: T): T[] {
return [arg]
}

使用泛型可以定义参数,比如上边的方法里定义了类型参数T,然后返回T[],就能完美的解决这个需求,这样写出来的函数就能知道返回值的类型是什么了。

泛型极大的增加了类型定义的灵活性,在很多复杂的类型定义中都会大规模的使用泛型来解决问题。

泛型接口

如果需要定义一个数值转化数组的泛型,字符串转化数组,还有布尔值转化数组这样的三个函数。那么可以这么去写。

我们需要的接口可能是一个“函数”。通过输入一个参数然后输出一个相应的接口。

interface Arrayify<T> {
(arg: T): T[]
}

const numberArrayify: Arrayify<number> = arg => {
return [arg]
}

const stringArrayify: Arrayify<string> = arg => {
return [arg]
}

const booleanArrayify: Arrayify<boolean> = arg => {
return [arg]
}

泛型类

使用react最常遇到的写法就是泛型类,比如

export default class Course extends React.Component<
RouteComponentProps,
CourseState
>

类根据泛型参数的不同,会表现出不同的特性,最常见的就是组件根据Component的props和state泛型参数,初始化的时候拥有不同的props和state。

泛型类和泛型接口差不多,都是根据参数的不同作出不同的表现。泛型类和泛型接口都极大的增强了类型约束的可塑性。

泛型约束

下边的函数需要log出参数的length,所以只能接受具有length属性的参数,可以通过extends来约束这个泛型的类型

interface WithLength {
length: number
}

function logLength<T extends WithLength>(arg: T): void {
console.log(arg.length)
}

泛型约束参数

如果需要实现一个函数的第二参数只能是一个参数的键时就需要用到keyof这个关键词,定义的第二个参数K extends keyof T表示K必须是T的键,这样如果第二个参数在第一个参数的键中找不到时就会抛出异常。

function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key]
}

let x = { a: 1, b: 2, c: 3, d: 4 }
getProperty(x, 'm')

keyof extends这些是typescript的有一个中的另一个领域的概念

枚举(enum)

写js的时候几乎不会用到枚举,顶多当我们需要枚举的时候会定义一个用来数据映射的对象。

而枚举在ts中相当于一种新的数据类型的声明方式,他的行为和对象一样,同时也可以作为类型使用

数字枚举

默认的枚举一组是自增的数值,比如下边的E和F是等价的,这种枚举通常用于我们对枚举的值完全不感兴趣的时候

enum E {
X,
Y,
Z
}

enum F {
X = 0,
Y = 1,
Z = 2
}

由于枚举自增的特性,因此下边的Y和Z分别会变成3和4。

enum E {
X = 2,
Y,
Z
}

反向映射

数字枚举可以通过枚举的索引获得他的键,这个叫做反向映射。

E[0] // X

字符串枚举

一般情况下定义的枚举都应该是字符串枚举,字符串枚举不能反向映射,也不能自增

enum Direction {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT'
}

枚举类型

枚举作为类型使用时,可以用来限制接口属性的值,假如超出枚举的范围就会出错。

enum TodoType {
EAT,
PLAY,
SLEEP
}

interface Todo {
type: TodoType
title: string
}

const todoList: Todo[] = [
{ type: TodoType.EAT, title: 'eat breakfast' },
{ type: TodoType.PLAY, title: 'play computer games' }
]

const枚举

为了减少打包出来的文件的体积大小,通常并不会需要把枚举对象一起打包进项目里,比如上面的那个todoList的demo其实编译之后的文件只需要那个数组就行了,这个时候就可以使用const枚举。

const enum TodoType {
EAT,
PLAY,
SLEEP
}

const枚举意味着这个枚举类型不会发生改变,因为不需要编译成一个对象,所以这个时候编译后的枚举对象将不会存在在代码中。

值得注意的是,这里的const和js里的const没有半毛钱的关系,这里的const指的是我不会变化,我不需要打包。

嗨,请先 登录

加载中...
(๑>ω<๑) 又是元气满满的一天哟