typeScript 新增的六个类型
1.元组
元组可以看做是数组的拓展,它表示已知元素数量和类型的数组。确切地说,是已知数组中每一个位置上的元素的类型,来看例子:
1 | let tuple: [string, number, string, boolean] |
2 | tuple = ['', 100, '', false] |
3 | tuple[1] = 200 |
4 | tuple[3] = true |
5 | |
6 | // 在 2.6 版本之前,TypeScript 对于元组长度的校验和 2.6 之后的版本有所不同,我们来看下面的例子,前后版本对于该情况的处理: |
7 | // tuple = ['', 100, '', false, ''] |
8 | // 不能将类型“[string, number, string, false, string]”分配给类型“[string, number, string, boolean]”。 |
9 | // 属性“length”的类型不兼容。 |
10 | // 不能将类型“5”分配给类型“4”。 |
2.枚举 enum
枚举 enum 类型在 C++这些语言中比较常见,TypeScript 在 ES 原有类型基础上加入枚举类型,使我们在 TypeScript 中也可以给一组数值赋予名字,这样对开发者来说较为友好。比如我们要定义一组角色,每一个角色用一个数字代表,就可以使用枚举类型来定义:
1 | enum Roles { |
2 | SUPER_ADMIN, |
3 | ADMIN = 100, |
4 | USER |
5 | } |
6 | |
7 | console.log(Roles[1]) // ADMIN |
8 | console.log(Roles.ADMIN) // 1 |
3.any
JavaScript 的类型是灵活的,程序有时也是多变的。有时,我们在编写代码的时候,并不能清楚地知道一个值到底是什么类型,这时就需要用到 any 类型,即任意类型。我们来看例子:
1 | let value: any |
2 | value = 'str' |
3 | value = false |
4 | value = null |
5 | value = undefined |
6 | value = 100 |
7 | console.log(value.name) |
8 | console.log(value.toFixed()) |
9 | console.log(value.length) |
10 | |
11 | // 上面这些语句都不会报错,因为 value 是 any 类型,所以后面三个操作都有合法的情况, |
12 | // 当 value 是一个对象时,访问 name 属性是没问题的;当 value 是数值类型的时候, |
13 | // 调用它的 toFixed 方法没问题;当 value 是字符串或数组时获取它的 length 属性是没问题的。 |
4.unknown
1 | let un: unknown |
2 | un = 'str' |
3 | un = false |
4 | un = null |
5 | un = undefined |
6 | un = 100 |
7 | |
8 | // console.log(un.name) // 对象的类型为 "unknown"。 |
9 | // console.log(un.toFixed()) |
10 | // console.log(un.length) |
11 | |
12 | // 而当你指定值为 unknown 类型的时候,如果没有通过基于控制流的类型断言来缩小范围的话, |
13 | // 是不能对它进行任何操作的,unknown 类型的值不是可以随便操作的。 |
5.void
void 和 any 相反,any 是表示任意类型,而 void 是表示没有任意类型,就是什么类型都不是,这在我们定义函数,函数没有返回值时会用到:
void 类型的变量只能赋值为 undefined 和 null,其他类型不能赋值给 void 类型的变量
1 | const voidFun = (text: string): void => { |
2 | console.log(text) |
3 | } |
4 | // 这个函数没有返回任何的值,所以它的返回类型为 void。 |
6.never
never 类型指那些永不存在的值的类型,它是那些总会抛出异常或根本不会有返回值的函数表达式的返回值类型,
// 当变量被永不为真的类型保护(后面章节会详细介绍)所约束时,该变量也是 never 类型。
1 | const errorFunc = (message: string): never => { |
2 | throw new Error(message) |
3 | } |
4 | |
5 | const infiniteFunc = (): never => { |
6 | while (true) { |
7 | console.log(100) |
8 | } |
9 | } |
交叉类型 (实际就是与的关系)
1 | const merge = <T, U>(arg1: T, arg2: U): T & U => { |
2 | let res = {} as T & U // as 语法 这里指定返回值的类型兼备 T 和 U 两个类型变量代表的类型的特点 |
3 | // let res = <T & U>{}; // 尖括号语法 |
4 | res = Object.assign(arg1, arg2) // 这里使用 Object.assign 方法,返回一个合并后的对象; |
5 | // 关于该方法,请在例子下面补充中学习 |
6 | return res |
7 | } |
8 | const info1 = { |
9 | name: 'lison' |
10 | } |
11 | const info2 = { |
12 | age: 18 |
13 | } |
14 | const lisonInfo = merge(info1, info2) |
15 | |
16 | console.log(lisonInfo.name) |
17 | // console.log(lisonInfo.address) // error 类型“{ name: string; } & { age: number; }”上不存在属性“address” |
18 | |
19 | // 可以看到,传入的两个参数分别是带有属性 name 和 age 的两个对象, |
20 | // 所以它俩的交叉类型要求返回的对象既有 name 属性又有 age 属性。 |
联合类型(实际就是或的关系)
联合类型在前面课时中几次提到,现在我们来看一下。联合类型实际是几个类型的结合,但是和交叉类型不同,联合类型是要求只要符合联合类型中任意一种类型即可,它使用 | 符号定义。当我们的程序具有多样性,元素类型不唯一时,即使用联合类型。
1 | const getLength = (content: string | number): number => { |
2 | if (typeof content === 'string') { |
3 | return content.length |
4 | } else { |
5 | return content.toString().length |
6 | } |
7 | } |
8 | console.log(getLength('abc')) // 3 |
9 | console.log(getLength(123)) // 3 |