# 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
类型,你就可以在它上面调用任何方法,访问任何属性,或者作为函数调用它。
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
类型。
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 会报错。
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
类型的变量上调用任何方法,访问任何属性,或者作为函数调用它。
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
。
function fn(): void {
console.log("Hello Cell");
}
// "use strict";
// function fn() {
// console.log("Hello Cell");
// }
# Null 和 Undefined 类型
在 TypeScript 中, undefined
和 null
两者有各自的类型分别为 undefined
和 null
。
let u: undefined = undefined;
let n: null = null;
# object,Object 和 {} 类型
# object 类型
object
类型表示非原始类型。
// 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;
# {} 类型
{}
类型描述了一个没有成员的对象,当试图访问其任意属性时,都会报错。
const obj = {};
obj.prop = 2022; // Error: Property 'prop' does not exist on type '{}'.
不过仍然可以使用在 Object 类型上定义的属性和方法。
代码语言:javascript复制const obj = {};
obj.toString(); // OK
# Never 类型
never
类型表示的是那些永不存在的值的类型。如,never
类型是那些总是会抛出异常或者根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型。
function error(message: string): never {
throw new Error(message);
}
可以使用 never
类型的特性来实现全面性检查。
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
避免出现新增了联合类型没有对应的实现,目的是写出类型绝对安全的代码