讲到TypeScript一定离不开它的类型系统,强类型约束是对原本弱类型的JavaScript的补充。而相对Java、C#等后端语言的标明类型系统(Nominal Type System),TypeScript采用的是结构类型系统(Structural Type System)。标明类型系统比较的是类型本身,具备非常强的一致性要求。结构类型系统比较的并不是类型定义本身,而是类型定义的形状。
高级类型
除了基本的对象类型、值类型外TypeScript还具有一些高级类型,例如交叉和联合类型。
type Point = {
x: number;
y: number;
};
type Name = {
name: string;
};
// 交叉类型:NamedPoint必须拥有Name和Point的所有成员
type NamedPoint = Name & Point;
// 联合类型:表示一个值可以是几种类型之一
type NamedPoint = Name | Point;
类型收缩
联合类型适合于那些值可以为不同类型的情况。但是存在需要对具体类型进行不同的处理。这时候就需要进行类型收缩。方式有
- typeof
- instanceof
- 字面量:自定义个字段名进行判断
- !断言
- as 断言
type Point = {
x: number;
y: number;
};
class obj {
point: Point | undefined;
constructor() {
this.point = { x: 1, y: 2 };
}
judge() {
// typeof
if (typeof this.point !== 'undefined') {
console.log(this.point.x);
}
// as断言
this.print(this.point as Point);
// !断言,去除null和undefined的情况
console.log(this.point!.x);
}
print(val: Point) {
console.log(val.x);
}
}
类型编程
TypeScript 可以进行类型层面的编程。方式有
- 泛型
- 别名
- keyof
- typeof
- 映射和索引
- extends
// 泛型
function identity<Type>(arg: Type): Type {
return arg;
}
// keyof
// 根据对象类型的成员,返回类型是字符串或数字,值为成员名的联合类型
type Point = { x: number; y: number };
type P = keyof Point;// 要求P是'x' | 'y'
// 特别的keyof any,要求其类型是string、number、symbol即可
// typeof
type K = keyof any;
let s = "hello";
let n: typeof s; // => let n: string
// 映射和索引
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
let point: Readonly<Point> = { x: 1, y: 12 };// 要求Ponit的成员只读
工具类型
TypeScript里已经声明了一些常用的类型可以当工具直接使用,无需定义即可使用,具体参考:es5声明类型 。这里简单讲下一些好用的。
对象工具
// 将类型T中的属性全部变成可选属性。
type Partial<T> = {
[P in keyof T]?: T[P];
};
// 将类型T中的属性全部变成必选属性
type Required<T> = {
[P in keyof T]-?: T[P];
};
// 返回一个对象类型,以K为key,以T为value。
type Record<K extends keyof any, T> = {
[P in K]: T;
};