TS 从 0 到 1 - 基础类型

2023-05-17 19:51:19 浏览数 (1)

# Boolean 类型

代码语言:javascript复制
let isDone: boolean = false;

# Number 类型

代码语言:javascript复制
let count: number = 2022;

# String 类型

代码语言:javascript复制
let name: string = "Cell";

# Symbol 类型

代码语言:javascript复制
let sym1: symbol = Symbol();
let sym2: symbol = Symbol("key"); // 可选的字符串 key

let obj = {
  [sym1]: "value"
};

console.log(obj[sym1]); // "value"

# Array 类型

代码语言:javascript复制
let list: number[] = [1, 2, 3];

let list: Array<number> = [1, 2, 3]; // Array<number> 泛型语法

# Enum 类型

# 数字枚举

代码语言:javascript复制
enum Direction {
  UP,
  DOWN,
  LEFT,
  RIGHT,
}

let dir: Direction = Direction.UP;

// "use strict";
// var Direction;
// (function (Direction) {
//     Direction[Direction["UP"] = 0] = "UP";
//     Direction[Direction["DOWN"] = 1] = "DOWN";
//     Direction[Direction["LEFT"] = 2] = "LEFT";
//     Direction[Direction["RIGHT"] = 3] = "RIGHT";
// })(Direction || (Direction = {}));
// let dir = Direction.UP;

默认情况下,从 0 开始为元素编号。 你也可以手动的指定成员的数值。 例如,我们将上面的例子改成从 1 开始编号:

代码语言:javascript复制
enum Direction {
  UP = 1,
  DOWN,
  LEFT,
  RIGHT,
}

let dir: Direction = Direction.UP;

// "use strict";
// var Direction;
// (function (Direction) {
//     Direction[Direction["UP"] = 1] = "UP";
//     Direction[Direction["DOWN"] = 2] = "DOWN";
//     Direction[Direction["LEFT"] = 3] = "LEFT";
//     Direction[Direction["RIGHT"] = 4] = "RIGHT";
// })(Direction || (Direction = {}));
// let dir = Direction.UP;

数字枚举还支持反向映射,从枚举值到枚举名字:

代码语言:javascript复制
enum Direction {
  UP = 1,
  DOWN,
  LEFT,
  RIGHT,
}

let dirName = Direction[2]; // "DOWN"
let dirVal = Direction["DOWN"]; // 2

# 字符串枚举

代码语言:javascript复制
enum Direction {
  UP = "UP",
  DOWN = "DOWN",
  LEFT = "LEFT",
  RIGHT = "RIGHT",
}

let dir: Direction = Direction.UP;

// "use strict";
// var Direction;
// (function (Direction) {
//     Direction["UP"] = "UP";
//     Direction["DOWN"] = "DOWN";
//     Direction["LEFT"] = "LEFT";
//     Direction["RIGHT"] = "RIGHT";
// })(Direction || (Direction = {}));
// let dir = Direction.UP;

# 常量枚举

代码语言:javascript复制
const enum Direction {
  UP,
  DOWN,
  LEFT,
  RIGHT,
}

let dir: Direction = Direction.UP;

// "use strict";
// let dir = 0 /* Direction.UP */;

# 异构枚举

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

代码语言:javascript复制
enum Enum {
  A,
  B,
  C = "C",
  D = "D",
  E = 8,
  F,
}

// "use strict";
// var Enum;
// (function (Enum) {
//     Enum[Enum["A"] = 0] = "A";
//     Enum[Enum["B"] = 1] = "B";
//     Enum["C"] = "C";
//     Enum["D"] = "D";
//     Enum[Enum["E"] = 8] = "E";
//     Enum[Enum["F"] = 9] = "F";
// })(Enum || (Enum = {}));

# Any 类型

在 TypeScript 中,任何类型都可以赋值给 any 类型,这让 any 类型成为了 TypeScript 中的顶级类型。

代码语言:javascript复制
let notSure: any = 2022;
notSure = "Cell";
notSure = false;

any 类型本质上是类型系统的一个逃逸仓,它允许你在编译时绕过类型检查。 一旦你将变量指定为 any 类型,你就可以在它上面调用任何方法,访问任何属性,或者作为函数调用它。

代码语言:javascript复制
let value: any;

value.foo.bar; // OK
value.trim(); // OK
value(); // OK
new value(); // OK
value[0][1]; // OK

# Unkonwn 类型

如果使用 any 类型,就无法使用 TypeScript 提供的大量的保护机制。为了解决 any 带来的问题,TypeScript 3.0 引入了 unknown 类型。

unknown 类型与 any 类型相似,所有类型也都可以赋值给 unknown 类型。

代码语言:javascript复制
let value: unknown;

value = 2022; // OK
value = "Cell"; // OK
value = false; // OK
value = {}; // OK
value = []; // OK
value = null; // OK
value = undefined; // OK
value = Symbol(); // OK
value = Math.random; // OK
value = new Date(); // OK
value = new Error(); // OK

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

代码语言:javascript复制
let value: unknown;

let val1: unknown = value; // OK
let val2: any = value; // OK

let val3: string = value; // Error
let val4: number = value; // Error
let val5: boolean = value; // Error
let val6: object = value; // Error
let val7: any[] = value; // Error
let val8: Function = value; // Error

只有能够保存任意类型值的容器才能保存 unknown 类型的值,因为不知道变量 value 的类型,所以不能将它赋值给其他类型的变量。

同样,也不能在 unknown 类型的变量上调用任何方法,访问任何属性,或者作为函数调用它。

代码语言:javascript复制
let value: unknown;

value.foo.bar; // Error
value.trim(); // Error
value(); // Error
new value(); // Error
value[0][1]; // Error

# Tuple 类型

元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。

代码语言:javascript复制
let tupleType: [string, number];

tupleType = ["Cell", 2022]; // OK
tupleType = [2022, "Cell"]; // Error

在元组初始化的时候,必须提供每个属性的值,不然会报错。

# Void 类型

void 类型表示没有任何类型,一般用于函数没有返回值的情况。从某种程度上来说,void 类型与 any 类型是相反的,严格模式下,void 类型的变量只能赋值为 undefined

代码语言:javascript复制
function fn(): void {
  console.log("Hello Cell");
}

// "use strict";
// function fn() {
//     console.log("Hello Cell");
// }

# Null 和 Undefined 类型

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

代码语言:javascript复制
let u: undefined = undefined;
let n: null = null;

# object,Object 和 {} 类型

# object 类型

object 类型表示非原始类型。

代码语言:javascript复制
// interface ObjectConstructor {
//   create(o: object | null): any;
// }

const proto = {};

Object.create(proto); // OK
Object.create(null); // OK
Object.create(undefined); // Error
Object.create(2022); // Error
Object.create("Cell"); // Error
Object.create(true); // Error
Object.create(Symbol()); // Error

# Object 类型

Object 类型是所有 Object 类的实例的的类型,由以下接口定义:

Object 接口定义了 Object.prototype 原型对象上的属性

代码语言:javascript复制
interface Object {
  constructor: Function;
  toString(): string;
  toLocaleString(): string;
  valueOf(): Object;
  hasOwnProperty(v: PropertyKey): boolean;
  isPrototypeOf(v: Object): boolean;
  propertyIsEnumerable(v: PropertyKey): boolean;
}

ObjectConstructor 接口定义了 Object 类的属性

代码语言:javascript复制
interface ObjectConstructor {
  new(value?: any): Object;
  (value?: any): any;
  readonly prototype: Object;
  getPrototypeOf(o: any): any;
  // ...
}

declare var Object: ObjectConstructor;

# {} 类型

{} 类型描述了一个没有成员的对象,当试图访问其任意属性时,都会报错。

代码语言:javascript复制
const obj = {};

obj.prop = 2022; // Error: Property 'prop' does not exist on type '{}'.

不过仍然可以使用在 Object 类型上定义的属性和方法。

代码语言:javascript复制
const obj = {};

obj.toString(); // OK

# Never 类型

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

代码语言:javascript复制
function error(message: string): never {
  throw new Error(message);
}

可以使用 never 类型的特性来实现全面性检查。

代码语言:javascript复制
type Foo = string | number;

function controlFlowAnalysisWithNever(foo: Foo) {
  if (typeof foo === "string") {
    // foo is string
  } else if (typeof foo === "number") {
    // foo is number
  } else {
    const check: never = foo;
  }
}

使用 never 避免出现新增了联合类型没有对应的实现,目的是写出类型绝对安全的代码

0 人点赞