1. 元组类型
元组就是数组的变种,它是固定数量的不同类型的元素组合。
当我们需要定义一个固定大小,不同类型值的数组时,就需要用到元组。
元组和数组的区别:
- 元组中的元素类型可以是不同的,而且数量是固定的。
- 数组中的元素类型需要是相同的,而且数量是不固定的。
元组的优势:如果一个方法需要返回多个值,可以把这多个值作为一个元组返回,不需要单独创建其他的类来表示。
1.1. 定义元组

ini
// 元组类型
type MyTuple = [number, string, boolean];
const tuple: MyTuple = [1, 'hello', true]; // 正确
// const tuple2: MyTuple = [1, 'hello', true, 'world']; // 错误,元组类型的长度必须与定义的一致
// const tuple3: MyTuple = [1, 'hello']; // 错误,元组类型的长度必须与定义的一致
1.2. 当赋值或访问一个已知索引的元素时,会得到正确的类型

arduino
// 当赋值或者访问一个已知索引的元素时,会得到正确的类型:
const firstElement: number = tuple[0]; // 正确,类型为 number
const secondElement: string = tuple[1]; // 正确,类型为 string
const thirdElement: boolean = tuple[2]; // 正确,类型为 boolean
1.3. 支持自定义名称和变为可选

typescript
// 支持自定义名称的元组类型:
type MyTupleWithNames = [first: number, second: string, third: boolean];
const tupleWithNames: MyTupleWithNames = [1, 'hello', true]; // 正确
const firstElementWithNames: number = tupleWithNames[0]; // 正确,类型为 number
// 可选性元组类型:
type MyOptionalTuple = [number?, string?, boolean?];
const optionalTuple: MyOptionalTuple = [1, 'hello']; // 正确,可选元素可以不提供
const optionalTuple2: MyOptionalTuple = [1, 'hello', true, 'world']; // 错误,可选元素的数量不能超过定义的数量
1.4. 越界元素
当访问一个越界的元素时,TypeScript 会将其视为一个数组类型。

typescript
// 越界元素的类型:
type MyTupleWithRest = [number, ...string[]]; // 表示第一个元素是 number,后面的元素是 string 类型的数组
const tupleWithRest: MyTupleWithRest = [1, 'hello', 'world']; // 正确,越界元素的类型是 string[]
2. 枚举类型
在 JS 中是没有枚举这个概念的,TS 帮我们定义了枚举类型,通过关键字 enum 定义。
2.1. 数字枚举
数字枚举的默认值是从 0 开始的,可以不写,默认为0.
我们也可以给枚举第一项赋值,其他成员会从我们赋值的数字开始自动增长。例如:我们给第一项赋值为1,那以此类推,第二项为2,第三项为3...。类似于数据库中的自增 id。

arduino
// 枚举类型
// 数字枚举
enum Role {
Reporter,
Developer,
Maintainer,
}
// 数组枚举的取值是从 0 开始递增的
console.log(Role.Reporter); // 0
console.log(Role.Developer); // 1
console.log(Role.Maintainer); // 2
// 增长枚举
enum Role1 {
Reporter=1,
Developer,
Maintainer,
}
2.2. 字符串枚举
字符串枚举的概念很容易理解,在一个字符串枚举中,每个成员都必须用字符串字面量,或另外一个字符串枚举成员初始化。
ini
// 字符串枚举
enum Message {
Success = '恭喜你,成功了',
Fail = '抱歉,失败了',
}
由于字符串枚举不能进行自增长,所以字符串枚举可以很好的进行序列化,相比于数字枚举,字符串枚举可以允许我们i提供一个运行时有意义并可读的值。独立与枚举成员的名字。这样更加能表达有用的信息。
2.3. 异构枚举
枚举可以混合字符串和数字,异构枚举就是一个即包含数字类型,又包含字符串类型的枚举。

arduino
// 异构枚举
enum Answer {
N,
Y = 'Yes',
}
2.4. 常量枚举
大多数的情况下,枚举是个十分有效的方案。在某些情况下要求很严格,为了避免其他代码额外对枚举成员的访问,造成性能的额外开销。我们可以使用 const 枚举。const 枚举在编译时会被编译成常量。而普通声明的枚举会被编译成一个对象。
注意:let 和 var 都是不能声明枚举的,只能使用 const

css
// 常量枚举
const enum Month {
Jan,
Feb,
Mar,
}
let month = [Month.Jan, Month.Feb, Month.Mar]; // 编译结果为 [0, 1, 2],而不是 ['Jan', 'Feb', 'Mar']
2.5. 接口枚举
接口枚举定义后,在使用该枚举时,声明接口要遵循该枚举的规则。

kotlin
// 接口枚举
enum Types {
A,
B,
}
interface IType {
type: Types; // 类型只能是 Types.A 或 Types.B
}
2.6. 反向映射
枚举时又反向映射属性的,当我们访问 name 时,会返回 value,访问 value 时,会返回 name。

ini
// 反向映射
enum Enum {
fall
}
let a = Enum.fall;
console.log(a); //0
let nameOfA = Enum[a];
console.log(nameOfA); //fall
2.7. 枚举成员
枚举类型可以包含多种类型的枚举成员
这里需要注意的是,数字没有 length 属性,不要去访问数字类型的 length

ini
// 枚举成员
enum Char {
// const
a,
b = Char.a,
c = 1 + 3,
// computed
d = Math.random(),
e = '123'.length,
f = 4,
}
3. never 类型
TS 使用 never 类型表示不应该存在的状态。
never 类型是最底层类型,它是所有类型的子类型,也可以赋值给任何类型;然而,没有类型是 never 的子类型或可以赋值给never 类型(除了 never 本身之外)。即使 any 也不可以赋值给 never。
下面是几种会出现 never 类型的例子。

typescript
// never类型
// 下面是一些使用never类型的例子:
// 1. 函数抛出错误:
function throwError(message: string): never {
throw new Error(message);
}
// 2. 死循环:
function infiniteLoop(): never {
while (true) { }
}
// 3. 无法到达的代码:
function unreachableCode(): never {
return 1; // 这个函数永远不会返回
}
// 4. 类型保护中的never:
function isNumber(value: any): value is number {
return typeof value === 'number';
}
function processValue(value: number | string): void {
if (isNumber(value)) {
console.log(value.toFixed(2)); // value 是 number 类型,这里可以安全调用 toFixed 方法
} else {
console.log(value.toUpperCase()); // value 是 string 类型,这里可以安全调用 toUpperCase 方法
}
}
// 5. 解构中的never:
function destructuringExample(): never {
const [x, y] = [1, 2]; // 解构数组时,x 和 y 的类型是 number
const { a, b } = { a: 1, b: 2 }; // 解构对象时,a 和 b 的类型是 number
}
// 6. 类型断言中的never:
function assertNever(value: never): never {
throw new Error("Unexpected object: " + value);
}
never 类型和 void 类型的区别
- never 类型是所有类型的子类型,而 void 类型不是。
- never 类型表示一个不可能存在的值,而 void 类型表示一个没有值的类型。
- never 类型通常用于表示函数的异常情况,而 void 类型通常用于表示函数的返回值类型。
- never 类型通常用于表示一个函数永远不会返回的情况,而 void 类型通常用于表示一个函数没有返回值的情况。
- never 类型在联合类型中会被直接移除,而 void 类型不会。