交叉类型
交叉类型是将多个类型合并为一个类型。用 & 表示。
interface IName {
name: string;
}
interface IAge {
age: number;
}
type Person = IName & IAge;
// person 同时有 IName 和 IAge 所有属性
const person: Person = {
name: "aa",
age: 100,
};
联合类型
联合类型表示一个值可以是几种类型之一。用竖线( | )分隔每个类型。
// 简单类型
function fn1(id: string | number) {
console.log(id); // id 是 string 或者 number 类型
}
// 复杂类型
interface ITeacher {
name: string;
id: string;
work: boolean;
}
interface IPerson {
name: string;
id: number;
}
// 如果一个值是联合类型,我们只能访问此联合类型的所有类型里共有的成员。
function fn(p: ITeacher | IPerson) {
console.log(p.id); // p.id 是 string 或者 number 类型
console.log(p.work); // 报错
}
type 类型别名
类型别名会给一个类型起个新名字。
起别名不会新建一个类型 - 它创建了一个新名字来引用那个类型。
type Str = string;
const s1: Str = "123";
类型别名和接口的区别
- 在检查类型的时候,接口会显示自己的类型名称,而类型别名则显示引用的那个类型的名称。
- 类型别名不能被 extends 和 implements,也不能 extends 和 implements 其它类型。应该尽量使用接口代替类型别名
字符串字面量类型
type Directions = "top" | "right" | "bottom" | "left";
// direction 只能从 IDirections 中选值
const direction: Directions = "top";
索引类型
keyof T 索引类型查询操作符
interface IPerson {
name: string;
age: number;
}
// 将接口 IPerson 的属性组成一个字符串字面量类型
type PersonProps = keyof IPerson;
const prop: PersonProps = "name";
T[K] 索引访问操作符
function getProperty<T, K extends keyof T>(o: T, name: K): T[K] {
return o[name];
}
映射类型
TypeScript 提供了从旧类型中创建新类型的一种方式 — 映射类型。 在映射类型里,新类型以相同的形式去转换旧类型里每个属性。
创建一个类型的只读版本
interface IPerson {
name: string;
age: number;
}
// 创建一个 IPerson 的只读版本
type ReadonlyPerson = {
readonly [P in keyof IPerson]: IPerson[P];
};
let p1: ReadonlyPerson;
// 通过泛型 创建一个通用的只读版本
type TReadonly<T> = {
readonly [P in keyof T]: T[P];
};
let p2: TReadonly<IPerson>;
它的语法与索引签名的语法类型,内部使用了 for .. in。 具有三个部分:
- 类型变量 K,它会依次绑定到每个属性。
- 字符串字面量联合的 Keys,它包含了要迭代的属性名的集合。
- 属性的结果类型。
其他常用类型
Exclude<T, U>
从类型 T 中排除可以指定为 U 的类型。
type Directions = "top" | "right" | "bottom" | "left";
const d1: Exclude<Directions, "top"> = "top"; // 报错
// Exclude 的源码实现
type Exclude<T, U> = T extends U ? never : T;
Extract<T, U>
与 Exclude 相反,从 T 中提取可以指定为 U 的类型
type Directions = "top" | "right" | "bottom" | "left";
const d2: Extract<Directions, "top"> = "top"; // d2 只能被赋值为 top
// Extract 的源码实现
type Extract<T, U> = T extends U ? T : never;
NonNullable<T>
从类型 T 中排除 null 和 undefined
type Mvalues = string | number | null | undefined;
const m: NonNullable<Mvalues> = null; // 报错,不能将 null 和 undefined 分配给 m
Omit<T, K>
构造一个除类型 K 以外具有 T 属性的类型。
interface IPerson {
name: string;
age: number;
}
const p: Omit<IPerson, "age"> = { name: "aa" };
// Omit 的源码实现
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
Partial<T>
将对象类型 T 中所有的属性变成可选的。
interface IPerson {
name: string;
age: number;
}
let p: Partial<IPerson> = { name: "aa" };
// Partial 的源码实现
type Partial<T> = {
[P in keyof T]?: T[P];
};
Pick<T, K>
从对象类型 T 中选择那些在类型 K 中的属性。
interface IPerson {
name: string;
age: number;
}
// 现在 p 只能有 name 一个属性
let p: Pick<IPerson, "name"> = { name: "aa" };
// Pick 的源码实现
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
Record<K, T>
构造一个对象类型,属性是 K 和 类型是 T
type Directions = "top" | "right" | "bottom" | "left";
type DValues = "1" | "2" | "3" | "4";
const d1: Record<Directions, DValues> = {
top: "1",
right: "2",
bottom: "3",
left: "4",
};
// Record 的源码实现
type Record<K extends keyof any, T> = {
[P in K]: T;
};
ReturnType<T>
获取函数返回值的类型。
let res1: ReturnType<(s: string) => string[]>; // let res1: string[]
// ReturnType<T> 的源码实现
type ReturnType<T extends (...args: any) => any> = T extends (
...args: any
) => infer R
? R
: any;