快速认知
TS允许我们为变量设置类型限制并进行检测判断
// 常见的类型判断
let age: number = 20;
let isDead: boolean = true;
let name: string = 'abc';
但是上面的写法太啰嗦了。ts有一个类型推断机制,ts会根据为变量赋的值自动给该变量设置一个类型。上面可以写为:
let age = 20;
let isDead = true;
let name = 'abc';
在上面的代码中,ts知道age就是一个数,isDead就是一个布尔值,name就是字符串,不需要显式设置变量类型。
当声明了一个变量但是没有设置初始值,建议为其设置一个类型
let ttt: string;
如果没有设置类型,那么它的类型会被设置为any,即接受任何值。
TS支持类型
Boolean 类型
let isDone: boolean = false;
Number 类型
let count: number = 10;
String 类型
let name: string = "Semliker";
Array 类型
let list: number[] = [1, 2, 3];
let list: string[] = ['1','2','3']
let list: Array<number> = [1, 2, 3]; // Array<number>泛型语法
至于什么是泛型,请看后面章
对象类型
1. 匿名对象类型
匿名对象类型是在定义变量时直接使用花括号{},来定义一个对象类型。例如:
const person: { name: string, age: number } = { name: 'John', age: 25 };
上述代码中定义了一个person变量,它的类型为对象,它有两个属性:name和age,其中name属性的类型为字符串,age属性的类型为数字。
2. 接口类型
使用接口来定义对象类型,可以使代码更加可读、易于维护。例如:
interface Person {name: string;age: number;}
const person: Person = { name: 'John', age: 25 };
上述代码中,定义了一个名为Person的接口,其中包括了两个属性:name和age。然后使用Person接口来定义了一个person变量,它的类型为Person接口。
你喜欢的话甚至可以把键名的类型也给限定了。
interface stringKeyObj {
[key: string]: string;
}
至于什么是接口,请看后面章节
3.类别类型
使用类型别名可以为对象类型定义简短、易读的名称。例如:
type Person = {name: string;age: number;}
const person: Person = { name: 'John', age: 25 };
有点像泛型。
上述代码中,使用type关键字定义了一个名为Person的类型别名,并通过花括号{}来定义了一个对象类型,其中有两个属性:name和age。然后使用Person类型别名来定义了一个person变量,它的类型为Person类型别名。
Any 类型
在 TypeScript 中,任何类型都可以被归为 any 类。也被称作全局超级类型)。使用any类型TS将不会对其进行任何检查。
let notSure: any = 666;
notSure = "Semlinker";
notSure = false;
可以对any类型的值进行任何操作
let value: any;
value.foo.bar; // OK
value.trim(); // OK
value(); // OK
new value(); // OK
value[0][1]; // OK
如果我们使用 any 类型,就无法使用 TypeScript 提供的大量的保护机制。为了解决 any 带来的问题,TypeScript 3.0 引入了 unknown 类型。
Unknown 类型
所有类型都可以赋值给 unknown。
let value: unknown
value = true; // OK
value = 42; // OK
value = "Hello World"; // OK
let value: unknown;
value = 123;
let value1: unknown = value; // OK
let value2: any = value; // OK
let value3: boolean = value; // Error
let value4: number = value; // Error
unknown 类型只能被赋值给 any 类型和 unknown 类型本身。不能赋值给其他类型。
只有能够保存任意类型值的容器才能保存 unknown类型的值。毕竟我们不知道变量 value 中存储了什么类型的值。
let value: unknown;
value.foo.bar; // Error
value.trim(); // Error
value(); // Error
new value(); // Error
value[0][1]; // Error
禁止对unkonwn类型的值进行任何修改操作
枚举类型Enum
TypeScript 支持数字的和基于字符串的枚举。
字符串枚举:
enum DataType {
/** @name 组织 */
Org = 'org',
/** @name 用户 */
User = 'user',
/** @name 角色 */
Role = 'role',
}
let dir: DataType = DataType.Org ;
数字枚举:
enum Direction {
/** 0 */
NORTH,
/** 1 */
SOUTH,
/** 2 */
EAST,
/** 3 */
WEST,
}
let a: Direction = Direction.SOUTH;
let b: Direction = Direction.WEST;
默认情况下,NORTH 的初始值为 0,其余的成员会从 1 开始自动增长。换句话说,Direction.SOUTH 的值为 1,Direction.EAST 的值为 2,Direction.WEST 的值为 3。
注意这个Direction 并不是生成类似于下面这种对象:
Direction = {
NORTH: 0,
SOUTH: 1,
EAST: 2,
WEST: 3,
}
而是:
{0: "NORTH",
1: "SOUTH",
2: "EAST",
3: "WEST",
NORTH: 0,
SOUTH: 1,
EAST: 2,
WEST: 3}
所以转换成JS便是:
var Direction;
(function (Direction) {
/** 0 */
Direction[Direction["NORTH"] = 0] = "NORTH";
/** 1 */
Direction[Direction["SOUTH"] = 1] = "SOUTH";
/** 2 */
Direction[Direction["EAST"] = 2] = "EAST";
/** 3 */
Direction[Direction["WEST"] = 3] = "WEST";
})(Direction || (Direction = {}));
var a = Direction.SOUTH;
var b = Direction.WEST;
Direction[Direction["NORTH"] = 0] = "NORTH";
这个看不懂?
其实就是:
Direction["NORTH"] = 0
Direction[0]="NORTH"
3.异构枚举
异构枚举的成员值是数字和字符串的混合:
enum Enum {
A,
B,
C = "C",
D = "D",
E = 8,
F,
}
Tuple 类型
JS的习惯性书写,TS的数组类型决定了数组一般由同种类型的值组成。,但有时我们需要在单个变量中存储不同类型的值,这时候我们就可以使用元组。在 JavaScript 中是没有元组的,元组是 TypeScript 中特有的类型,其工作方式类似于数组。
- 元组可用于定义具有有限数量的未命名属性的类型。每个属性都有一个关联的类型。
- 使用元组时,必须提供每个属性的值。为了更直观地理解元组的概念
let tupleType: [string, boolean];
tupleType = ["Semlinker", true];
类型检测:
同时也会进行长度检测:
Void 类型
void 类型像是与 any 类型相反,它表示没有任何类型。当一个函数没有返回值时,你通常会见到其返回值类型是 void:
function xxx(): void {
console.log("123");
}
以上代码编译生成的 ES5 :
"use strict";
function xxxx() {
console.log("123");
}
如果用Void类型来定义变量,那么它只能接受undefined的值
Null 和 Undefined 类型
undefined 和 null 分别定义为 undefined 类型和 null类型
let u: undefined = undefined;
let n: null = null;
Never 类型
表示的是那些永不存在的值的类型。
// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
throw new Error(message);
}
function infiniteLoop(): never {
while (true) {}
}
never 类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型。
听起来没什么用。实际上,我们在项目用Never类型进行全面性检查:
type Foo = string | number;
function controlFlowAnalysisWithNever(foo: Foo) {
if (typeof foo === "string") {
// 这里 foo 被收窄为 string 类型
} else if (typeof foo === "number") {
// 这里 foo 被收窄为 number 类型
} else {
// foo 在这里是 never
const check: never = foo;
}
}