likes
comments
collection
share

🚀🚀🚀Typescript通关秘籍(三)🔥🔥🔥

作者站长头像
站长
· 阅读数 2

新的类型

TS 中除了 JS 原本的类型外,还增加了几个新类型,接下来,我们来瞧瞧都有谁。👀

Any

any 类型表示没有任何限制,它可以赋值给任何类型,任何类型也可以赋值给它。

它通常被称为 Top type any,即顶层类型。一旦设置为 any 类型,TS 实际上会关闭类型检查,它会认为开发者想自己来处理这些代码。

let articleName: any;

articleName = '橙某人';
articleName = 18;
articleName = true;

一般建议尽可能少使用 any 类型。🔞

Unknown

unknown 被视为严格版的 any,任何类型都能赋值给 unknown 类型,但是反之不行,它只能赋值给 any 类型和本身。

let articleName: unknown;

articleName = '橙某人';
articleName = 18;
articleName = true;

let str: string;
let num: number;
let bool: boolean;

str = articleName; // ❌
num = articleName; // ❌
bool = articleName; // ❌

unkown 也属于顶层类型。

Never

never 类型表示空类型,或者说是指不存在的类型或者状态。

TS 引入了 "空类型" 的概念,即该类型为空,不包含任何值,也不可能存在这样的值。

它能赋值给任意其他类型,反之不行。

let nev = ():never => {
  throw new Error('Error');
};

let str: string;
let num: number;
let bool: boolean;

str = nev();
num = nev();
bool = nev();

nev = str; // ❌
nev = num; // ❌
nev = bool; // ❌

它一般会被应用在函数中,表示函数出现异常的情况,如函数运行抛出错误、函数出现死循环情况、或者是判断分支溢出等等。

Void

void 类型表示没有返回值,一般用来描述函数、Promise 等的返回值类型。

const fn = ():void => {};

const promise = new Promise<void>(resolve => resolve());
promise.then(res => {
  // res: void
});

voidundefined 的子类型。

let voi: void;

voi = undefined;
voi = void 1;

void 其实和 undefined 是一样的,但是为什么还需要它呢?这还是因为 undefinedJS 中是允许被随意覆盖的,而 void 才是真正意义上的 undefined

Tuple - 元组

元组(tuple)可以看成是数组(Array)类型的一个特殊扩展,它精确地知道它包含了多少个元素,以及它在特定位置包含哪些类型。

🔉"一一对应,不多不少"

let arr: [string, number, boolean] = ['橙某人', 18, true];

let arr1: [string, number, boolean] = ['橙某人', 18]; // ❌
let arr2: [string, number, boolean] = ['橙某人', 18, true, undefined]; // ❌

无法自动推断

使用元组时,必须明确给出类型声明,否则 TS 会把它自动推断为数组类型。

let arr = ['橙某人', 18, true]; // (string | number | boolean)[]

可选成员

元组成员的类型也能变成可选(?)的,但它必须被放在最后一项。

let arr: [string, number, c?: boolean] = ['橙某人', 18];

let arr1: [string, c?: boolean, number] = ['橙某人', undefined, 18]; // ❌

🚀🚀🚀Typescript通关秘籍(三)🔥🔥🔥

扩展运算符(...)

元组中也可以使用扩展运算符(...),并且它能在元组中的任意位置,但是它后面只能是数组或者元组。

let arr1: [string, ...number[]] = ['橙某人', 18];
let arr2: [...number[], string] = [18, '橙某人'];
let arr3: [string, ...number[], boolean] = ['橙某人', 18, 20, true];

// 元组
let arr4: [string, ...[number, boolean], number] = ['橙某人', 18, true, 1];

Enum - 枚举

枚举(enum)是 TS 新增加一种数据结构,同时它也是一种类型。

枚举可以分类成三种形式:数字枚举、字符串枚举、混合枚举(不推荐)。

数字枚举

enum Color {
  red = 0,
  green = 1,
  blue = 2,
}

console.log(Color.red); // 0
console.log(Color.green); // 1
console.log(Color.blue); // 2

默认情况下,数字枚举成员会从0开始自动增长。

enum Color {
  red,
  green,
  blue,
}

console.log(Color.red); // 0
console.log(Color.green); // 1
console.log(Color.blue); // 2

并且是相对上一个数字成员增长。

enum Color {
  red,
  green = 3,
  blue,
}

console.log(Color.red); // 0
console.log(Color.green); // 3
console.log(Color.blue); // 4

当然,你可能会想到这种情况:

enum Color {
  red,
  green = 'g',
  blue,
}

🚀🚀🚀Typescript通关秘籍(三)🔥🔥🔥

这种情况是不被允许的,它要求 Color.blue 必须初始化。

字符串枚举

字符串枚举是在 TS2.4 版本才被引入的,字符串枚举的所有成员值,都必须显式设置。

enum Color {
  red = 'r',
  green = 'g',
  blue = 'b'
}

同名自动合并

多个同名的枚举结构会自动进行合并,并且在只有第一个枚举声明可以省略其初始化表达式。

enum Color {
  red,
}

enum Color {
  green = 1, // 必须初始化
}

enum Color {
  blue = 2, // 必须初始化
}

多个同名的枚举进行合并的时候,不能有同名的成员。

enum Color {
  red,
}

enum Color {
  green = 1,
}

enum Color {
  red, // ❌
}

反向映射

什么是反向映射呢?这是数字枚举成员才有的一种特性,其实就是双向能相互访问(key <=> value)。

enum Color {
  red,
  green,
  blue
}

console.log(Color.red); // 0
console.log(Color[0]); // red

可以来看看它是如何来实现的,执行 tsc 命令编译成 ES5 代码。

var Color;
(function (Color) {
    Color[Color["red"] = 0] = "red";
    Color[Color["green"] = 1] = "green";
    Color[Color["blue"] = 2] = "blue";
})(Color || (Color = {}));

/* Color: 
{
  "red": 0,
  "green": 1,
  "blue": 2,
  "0": "red",
  "1": 'green",
  "2": "blue"
}
*/

再来看看字符串枚举成员的编译结果:

enum Color {
  red = 'r',
  green = 'g',
  blue = 2
}

var Color;
(function (Color) {
    Color["red"] = "r";
    Color["green"] = "g";
    Color[Color["blue"] = 2] = "blue";
})(Color || (Color = {}));

/* Color:
{
  "2": "blue",
  "red": "r",
  "green": "g",
  "blue": 2
}
*/

作为类型使用

enum Color {
  red,
  green,
  blue,
}

let color1: Color = 0;
let color2: Color.red = Color.red;

let color3: Color.red = Color.green; // ❌

枚举不能修改-const

枚举有点像"常量"的意思,它的成员值都是只读,不允许再修改。

enum Color {
  red,
  green,
  blue,
}

Color.red = 3; // ❌

enum 关键字前面还可以加上 const 修饰符。

const enum Color {
  red,
  green,
  blue,
}

const 修饰符能更加明确表达枚举不可被修改的特性,并且它们在编译之后还有所不同。

enum Color {
  red,
  green,
  blue,
}

let red = Color.red;
let green = Color.green;
let blue = Color.blue;

/* 编译后:
var Color;
(function (Color) {
    Color[Color["red"] = 0] = "red";
    Color[Color["green"] = 1] = "green";
    Color[Color["blue"] = 2] = "blue";
})(Color || (Color = {}));
var red = Color.red;
var green = Color.green;
var blue = Color.blue;
*/
const enum Color {
  red,
  green,
  blue,
}

let red = Color.red;
let green = Color.green;
let blue = Color.blue;

/* 编译后:
var red = 0;
var green = 1;
var blue = 2;
*/

加上 const 修饰符的枚举,其枚举成员会被直接替换成对应的值,这在一定程度上能起到提高性能的作用。

🍊关于枚举出现的作用或意义?

枚举的作用能替代魔法数字、提高代码的可读性和扩展性、增加编辑器的代码提示和自动补全。


至此,本篇文章就写完啦,撒花撒花。

🚀🚀🚀Typescript通关秘籍(三)🔥🔥🔥

希望本文对你有所帮助,如有任何疑问,期待你的留言哦。 老样子,点赞+评论=你会了,收藏=你精通了。