• 静态类型: null, undefined, symbol, boolean, number, string, void
  • 对象类型: {}, class, function, []

基础静态类型

  1. let b: number = 123;
  2. let firstName: string = "Jack"

对象类型类型

  1. const teacher: {
  2. name: string,
  3. age: number
  4. } = {
  5. name: 'Jack',
  6. age: 28
  7. }
  8. const numbers: number[] = [1,2,3]
  9. // 或者使用数组泛型
  10. let arr: Array<number> = [1, 2];
  11. class Person {}
  12. const jack: Person = new Person()
  13. // 返回类型是数字
  14. const getTotal: () => number = () => {
  15. return 123;
  16. }

注意: {} 等价 Object, 与object有区别

TypeScript VS JavaScript

类型 TypeScript JavaScript
null
undefined
boolean
number, double??
string
array
ts特有 never
unknow
any
enum
tuple
void

2.1 Boolean 类型

  1. let isDone: boolean = false;
  2. // ES5:var isDone = false;

2.2 Number 类型

  1. let count: number = 10;
  2. // ES5:var count = 10;

2.3 String 类型

  1. let name: string = "Semliker";
  2. // ES5:var name = 'Semlinker';

2.4 Symbol 类型

  1. let s1: symbol = Symbol() // 具有唯一的值
  2. let s2 = Symbol()
  3. // console.log(s1 === s2) 不相等

2.5 Enum 类型

使用枚举我们可以定义一些带名字的常量。 使用枚举可以清晰地表达意图或创建一组有区别的用例。 TypeScript 支持数字的和基于字符串的枚举。

1.数字枚举

  1. enum Direction {
  2. NORTH,
  3. SOUTH,
  4. EAST,
  5. WEST,
  6. }
  7. let dir: Direction = Direction.NORTH;

默认情况下,NORTH 的初始值为 0,其余的成员会从 1 开始自动增长。换句话说,Direction.SOUTH 的值为 1,Direction.EAST 的值为 2,Direction.WEST 的值为 3。上面的枚举示例代码经过编译后会生成以下代码:

  1. "use strict";
  2. var Direction;
  3. (function (Direction) {
  4. Direction[(Direction["NORTH"] = 0)] = "NORTH";
  5. Direction[(Direction["SOUTH"] = 1)] = "SOUTH";
  6. Direction[(Direction["EAST"] = 2)] = "EAST";
  7. Direction[(Direction["WEST"] = 3)] = "WEST";
  8. })(Direction || (Direction = {}));
  9. var dir = Direction.NORTH;

当然我们也可以设置 NORTH 的初始值,比如:

  1. enum Direction {
  2. NORTH = 3,
  3. SOUTH,
  4. EAST,
  5. WEST,
  6. }

如果它没有初始化方法,那么它的初始值为0

  1. enum Status {
  2. OFFLINE,
  3. ONLINE,
  4. DELETED
  5. }
  6. // 0, 1, 2
  7. // { "0": "OFFLINE", "1": "ONLINE", "2": "DELETED", "OFFLINE": 0, "ONLINE": 1, "DELETED": 2 }
  8. enum Status {
  9. OFFLINE = 1,
  10. ONLINE,
  11. DELETED
  12. }
  13. // 1, 2, 3
  14. // { "1": "OFFLINE", "2": "ONLINE", "3": "DELETED", "OFFLINE": 1, "ONLINE": 2, "DELETED": 3 }
  15. enum Status {
  16. OFFLINE,
  17. ONLINE = 4,
  18. DELETED
  19. }
  20. // 0, 4, 5
  21. // { "0": "OFFLINE", "4": "ONLINE", "5": "DELETED", "OFFLINE": 0, "ONLINE": 4, "DELETED": 5 }

2.字符串枚举
在 TypeScript 2.4 版本,允许我们使用字符串枚举。在一个字符串枚举里,每个成员都必须用字符串字面量,或另外一个字符串枚举成员进行初始化。

  1. enum Direction {
  2. NORTH = "NORTH",
  3. SOUTH = "SOUTH",
  4. EAST = "EAST",
  5. WEST = "WEST",
  6. }

3.异构枚举
异构枚举的成员值是数字和字符串的混合:

  1. enum Enum {
  2. A,
  3. B,
  4. C = "C",
  5. D = "D",
  6. E = 8,
  7. F,
  8. }

2.6 Any 类型

在 TypeScript 中,任何类型都可以被归为 any 类型。这让 any 类型成为了类型系统的顶级类型(也被称作全局超级类型)。

  1. let notSure: any = 666;
  2. notSure = "Semlinker";
  3. notSure = false;

any 类型本质上是类型系统的一个逃逸舱。作为开发者,这给了我们很大的自由:TypeScript 允许我们对 any 类型的值执行任何操作,而无需事先执行任何形式的检查。比如:

  1. let value: any;
  2. value.foo.bar; // OK
  3. value.trim(); // OK
  4. value(); // OK
  5. new value(); // OK
  6. value[0][1]; // OK

在许多场景下,这太宽松了。使用 any 类型,可以很容易地编写类型正确但在运行时有问题的代码。如果我们使用 any 类型,就无法使用 TypeScript 提供的大量的保护机制。为了解决 any 带来的问题,TypeScript 3.0 引入了 unknown 类型。

2.7 Unknown 类型

就像所有类型都可以赋值给 any,所有类型也都可以赋值给 unknown。这使得 unknown 成为 TypeScript 类型系统的另一种顶级类型(另一种是 any)。下面我们来看一下 unknown 类型的使用示例:

  1. let value: unknown;
  2. value = true; // OK
  3. value = 42; // OK
  4. value = "Hello World"; // OK
  5. value = []; // OK
  6. value = {}; // OK
  7. value = Math.random; // OK
  8. value = null; // OK
  9. value = undefined; // OK
  10. value = new TypeError(); // OK
  11. value = Symbol("type"); // OK

value 变量的所有赋值都被认为是类型正确的。但是,当我们尝试将类型为 unknown 的值赋值给其他类型的变量时会发生什么?

  1. let value: unknown;
  2. let value1: unknown = value; // OK
  3. let value2: any = value; // OK
  4. let value3: boolean = value; // Error
  5. let value4: number = value; // Error
  6. let value5: string = value; // Error
  7. let value6: object = value; // Error
  8. let value7: any[] = value; // Error
  9. let value8: Function = value; // Error

unknown 类型只能被赋值给 any 类型和 unknown 类型本身。直观地说,这是有道理的:只有能够保存任意类型值的容器才能保存 unknown 类型的值。毕竟我们不知道变量 value 中存储了什么类型的值。
现在让我们看看当我们尝试对类型为 unknown 的值执行操作时会发生什么。以下是我们在之前 any 章节看过的相同操作:

  1. let value: unknown;
  2. value.foo.bar; // Error
  3. value.trim(); // Error
  4. value(); // Error
  5. new value(); // Error
  6. value[0][1]; // Error

value 变量类型设置为 unknown 后,这些操作都不再被认为是类型正确的。通过将 any 类型改变为 unknown 类型,我们已将允许所有更改的默认设置,更改为禁止任何更改。

2.8 Tuple 类型

众所周知,数组一般由同种类型的值组成,但有时我们需要在单个变量中存储不同类型的值,这时候我们就可以使用元组。在 JavaScript 中是没有元组的,元组是 TypeScript 中特有的类型,其工作方式类似于数组。
元组可用于定义具有有限数量的未命名属性的类型。每个属性都有一个关联的类型。使用元组时,必须提供每个属性的值。为了更直观地理解元组的概念,我们来看一个具体的例子:

  1. let tupleType: [string, boolean];
  2. tupleType = ["Semlinker", true];

在上面代码中,我们定义了一个名为 tupleType 的变量,它的类型是一个类型数组 [string, boolean],然后我们按照正确的类型依次初始化 tupleType 变量。与数组一样,我们可以通过下标来访问元组中的元素:

  1. console.log(tupleType[0]); // Semlinker
  2. console.log(tupleType[1]); // true

在元组初始化的时候,如果出现类型不匹配的话,比如:

  1. tupleType = [true, "Semlinker"];

此时,TypeScript 编译器会提示以下错误信息:

  1. [0]: Type 'true' is not assignable to type 'string'.
  2. [1]: Type 'string' is not assignable to type 'boolean'.

很明显是因为类型不匹配导致的。在元组初始化的时候,我们还必须提供每个属性的值,不然也会出现错误,比如:

  1. tupleType = ["Semlinker"];

此时,TypeScript 编译器会提示以下错误信息:

  1. Property '1' is missing in type '[string]' but required in type '[string, boolean]'.

2.9 Void 类型

某种程度上来说,void 类型像是与 any 类型相反,它表示没有任何类型。当一个函数没有返回值时,你通常会见到其返回值类型是 void:

  1. // 声明函数返回值为void
  2. function warnUser(): void {
  3. console.log("This is my warning message");
  4. }

以上代码编译生成的 ES5 代码如下:

  1. "use strict";
  2. function warnUser() {
  3. console.log("This is my warning message");
  4. }

需要注意的是,声明一个 void 类型的变量没有什么作用,因为它的值只能为 undefinednull

  1. let unusable: void = undefined;

2.10 Null 和 Undefined 类型

TypeScript 里,undefinednull 两者有各自的类型分别为 undefinednull

  1. let u: undefined = undefined;
  2. let n: null = null;

默认情况下 nullundefined 是所有类型的子类型。 就是说你可以把 nullundefined 赋值给 number 类型的变量。然而,如果你指定了**--strictNullChecks** 标记,**null****undefined** 只能赋值给 **void** 和它们各自的类型。

2.11 Never 类型

never 类型表示的是那些永不存在的值的类型。 例如,never 类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型。

  1. // 返回never的函数必须存在无法达到的终点
  2. function error(message: string): never {
  3. throw new Error(message);
  4. }
  5. function infiniteLoop(): never {
  6. while (true) {}
  7. }

在 TypeScript 中,可以利用 never 类型的特性来实现全面性检查,具体示例如下:

  1. type Foo = string | number;
  2. function controlFlowAnalysisWithNever(foo: Foo) {
  3. if (typeof foo === "string") {
  4. // 这里 foo 被收窄为 string 类型
  5. } else if (typeof foo === "number") {
  6. // 这里 foo 被收窄为 number 类型
  7. } else {
  8. // foo 在这里是 never
  9. const check: never = foo;
  10. }
  11. }

几种语言的对比

  1. var name = "Jack"; // JavaScript
  2. var name: string = "Jack"; // TypeScript
  3. string name = "Jack"; // Dart
  4. var name string = "Jack"; // Golang

建议学习的几种库:


缺少声明文件

image.png
解决: 添加辅助声明

什么是d.ts❓

index.d.ts 匹配 index.js
生成d.ts