Partial
定义
/**
* Make all properties in T optional
*/
type Partial<T> = {
[P in keyof T]?: T[P];
};
- in操作符作用:遍历类型,可以理解为 for-in循环
- keyof(索引类型查询操作符):是将一个类型映射为它所有成员名称的联合类型。
interface Pokemon {
pikachu: string;
squirtle: string;
charmander: string;
}
// 使用keyof 得到所有属性的联合类型
type test = keyof Pokemon //相当于pikachu | squirtle | charmander;
所以这里 P in keyof T相当 for-in 遍历。然后加上中括号[P in keyof T]变成一个动态的索引类型
- 外层的?操作符,让属性变成可选项,也就是遍历的每一项属性都会变成可选的
- T[P] 索引访问操作符,相当于js里面访问对象的值
Partial的使用
将一个已知的类型每个属性都变为可选的
interface Pokemon {
pikachu: string;
squirtle: string;
charmander: string;
}
// 将接口的属性都变成可选的
type test = Partial<Pokemon>;
// 相当于
type test = {
pikachu?: string | undefined;
squirtle?: string | undefined;
charmander?: string | undefined;
}
//对比源码
type Partial<T> = {
[P in keyof T]?: T[P];
};
/*
以上面的例子解释Partial的运行
1.首先是传入Pokemon类型,所以 T类型就是Pokemon
2.keyof T:都到所有Pokemon的属性名的联合类型,也就是 pikachu | squirtle | charmander
3.P in keyof T:相当于 p in pikachu | squirtle | charmander ,遍历这个属性名形成的联合类型
4.P in keyof T]?: T[P]:最后就是每一个动态索引类型([P in keyof T]) 加上可选符号(?)给他声明为 Pokemon类型的属性值类型
*/
Required
定义
/**
* Make all properties in T required
*/
type Required<T> = {
[P in keyof T]-?: T[P];
};
有了上面Partial可选类型的理解,Required其实就很容易了 使用了-? 就是去掉每一个属性的可选,于是就成为了必须
Required的使用
将一个已知的类型每个属性都变为必须的
interface Pokemon {
pikachu?: string;
squirtle?: string;
charmander?: string;
}
//作用就是所有属性转为必要的
type test = Required<Pokemon>;
// 相当于
type test = {
pikachu: string;
squirtle: string;
charmander: string;
}
Readonly
定义
/**
* Make all properties in T readonly
*/
type Readonly<T> = {
readonly [P in keyof T]: T[P];
}
使用和Required,形成一个只能访问不能操作的新类型
Readonly的使用
将一个已知的类型每个属性都变为只读的
interface Pokemon {
pikachu: string;
squirtle: string;
charmander: string;
}
type test = Readonly<Pokemon>;
//相当于
type test = {
readonly pikachu: string;
readonly squirtle: string;
readonly charmander: string;
}
Pick
定义
/**
* From T, pick a set of properties whose keys are in the union K
*/
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
这里出现了extends,而在ts中extends关键字在不同场景有不同的用法
- 表示继承
- 表示约束
- 表示选择
- 表示分配
K extends keyof T这里的extends表示约束,也就是泛型约束,相当于K 是 keyof T的子集
Pick的使用
从一个已知的类型选出所需要的属性
interface Pokemon {
pikachu: string;
squirtle: string;
charmander: string;
}
//从Pokemon中取出charmander,pikachu 生成一个新类型
type test = Pick<Pokemon, 'charmander' | 'pikachu'>;
//相当于
type test = {
charmander: string;
pikachu: string;
}
Record
定义
/**
* Construct a type with a set of properties K of type T
*/
type Record<K extends keyof any, T> = {
[P in K]: T;
};
其中keyof any 返回 string number symbol 的联合类型
所以产生的新属性名的类型约束为string |number |symbol,而属性值的类型是T
Record的使用
用来定义(约束)对象的键和值
interface Pokemon {
pikachu: string;
squirtle: string;
charmander: string;
}
type test = Record<keyof Pokemon, keyof Pokemon>;
//相当于
type test = {
pikachu: keyof Pokemon;
squirtle: keyof Pokemon;
charmander: keyof Pokemon;
}
//使用Record约束test类型的属性名、属性值都为为Pokemon的属性名类型
Exclude
定义
/**
* Exclude from T those types that are assignable to U
*/
type Exclude<T, U> = T extends U ? never : T;
/**
* 从`T`中剔除可以赋值给`U`的类型。
* 这句源码相当于三元运行符,如果T属于U(T是U的子集),那么取值never,否者取值T
* 出现了第二个extends的用法这里既可以是表示分配或者选择
* 如果传入的T是一个联合类型就是分配,否者就表示选择
*/
Exclude的使用
Exclude<T, U> -- 从T中剔除可以赋值给U的类型。
/*
* type Exclude<T, U> = T extends U ? never : T;
* 对照着源码进行使用
*/
// 1.extends表示选择,三元运算符的用法的直接体现
type test = Exclude<number, string>; // 因为number 不是string的自己,所以取值为number
// 2.extends这里表示分配因为T这里对应的是number|string|symbol的联合类型,所以联合类型的每一项都要和string做运算
type test2 = Exclude<number|string|symbol, string>; // number|symbol
Extract
定义
/**
* Extract from T those types that are assignable to U
*/
type Extract<T, U> = T extends U ? T : never;
// 从源码上看出和Exclude比结果是相反的
Extract使用
Extract<T, U> -- 提取T中可以赋值给U的类型。
type test = Extract<string | symbol, number | string | symbol>; // string|symbol
Omit
定义
/**
* Construct a type with the properties of T except for those in type K.
*/
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
/**
* 对于Pick<T, Exclude<keyof T, K>>
* 其中Exclude<keyof T, K> 获取T的联合类型中不属于K的,接着从T中选择这些不属于它的
* 最后 K extends keyof any:在Record上有说明,所以K被约束成 number|string|sybmol的联合类型的子集
* 总结:剔除T中的某些属性,返回一个新类型。
/**
Omit使用
`Omit<T, K>` -- 剔除`T`中的K属性
interface Pokemon {
pikachu: string;
squirtle: string;
charmander: string;
}
type test = Omit<Pokemon, "pikachu">;
/**相当于
* type test = {
* squirtle: string;
* charmander: string;
} */