Appearance
映射类型的属性过滤
上面我们通过Pick + Exclude实现了Omit类型工具,那我们能不能完全自己实现,不借助已有的类型工具呢?也可以,不过我们需要掌握一个技巧:通过as + never实现属性过滤的效果
typescript
type User = {
readonly id: number;
name: string;
tel: string;
address?: string;
};
type MyOmit<T, K extends keyof T> = {
[P in keyof T as P extends K ? never : P]: T[P];
};
type A = MyOmit<User, 'tel' | 'address'>; // {readonly id: number; name: string}在例子中,映射 K in keyof T 获取类型 T 的每一个属性以后,后面紧跟着as其实是可以为键重新映射命名的
不过现在,它的键名重映射 as P extends K ? never : P,使用了条件运算符,又会触发分布式处理
原始属性 P | 逻辑判断 (P extends K) | 映射结果 |
|---|---|---|
"id" | false | "id" |
"name" | false | "name" |
"tel" | true | never |
"address" | true | never |
最终合并键集合:"id" | "name" | never | never => "id" | "name"
我们还能再升级一下,比如:只保留User值类型是string类型的,生成新的类型
typescript
type PickStringValueType<T> = {
[K in keyof T as T[K] extends string ? K : never]: T[K];
};
type FilteredUser = PickStringValueType<User>; //{name:string, tel:string}当然,你想反过来,去掉值类型是string类型的,将K和never换个位置就行了
其实上面做的更加普遍性一些,就完全可以写成一个类型工具:
typescript
type PickByType<T, U> = {
[P in keyof T as T[P] extends U ? P : never]: T[P];
};
type B = PickByType<User, number>; // { readonly id: number }