TypeScript学习-进阶1
1.数据转换
在工作或学习过程中,经常会遇到数据类型不完全匹配的情况,例如从后端返回的数据类型,部分类型并不满足前端的需要,会导致后端写一份类型,前端还要重写一遍类型,导致冗余类型过多
例如:
// 假设后端的数据类型为:
type ProductBody = {
height:number,
width:number,
weight:number,
}
type ProductTest = {
test1?:string,
test2:number,
test3:number,
}
type ProductInfo = {
id?:number,
name:string,
num:number, //编号
count:number,
price:number,
body:ProductBody[],
month?:string,
test:ProductTest
}
需要通过一个方式,获得如下类型:
// 假设后端的数据类型为:
type ProductBodyForView = {
height:number | null,
width:number | null,
weight:number | null,
}
type ProductTestForView = {
test1:string,
test2:number,
test3:number,
}
type ProductInfoForView = {
id?:number,
name:string,
num:number | null, //编号
count:number | null,
price:number | null,
body:ProductBodyForView[],
month:string,
test:ProductTestForView,
}
那么如何将ProductInfo类型转为ProductInfoForView这样的类型呢?首先可以分析一下,数据结构中所有的number类型都转为了number | null,先完成这一步:
/** 将所有的 number/number | undefined类型转为 number | null/number | undefined | null */
export type ToNumberOrNull<T> = {
[P in keyof T]: T[P] extends number ? number | null :
T[P] extends number | undefined ? number | null | undefined :
T[P]
}
做完这一步之后,我们已经可以将number类型都转为了number | null,然后再分析一下,我们还需要将ProductInfo这个类型中的body转为ProductBodyForView ,test这个类型转为ProductTestForView,当然可以这样来转:
type ProductInfoForView = Omit<ProductInfo,'body' | 'test'> & {
body:ProductBodyForView[],
test:ProductTestForView
}
这样当然是ok的,但这只是有两个key的类型需要转换,那么如果有10个key,就要Omit<ProductInfo,‘xx’ | ‘xx’ …> & {xx:xx,xx:xx…},手写抽筋了!
那有没有办法能简写一点呢,有的:
// 核心
export type ParseData<T, K extends { [P in keyof K]: K[P] }> = {
[M in keyof Required<T>]: M extends keyof K ? K[M] : T[M]
}
用法:
type ParseData = ParseData<ToNumberOrNull<Required<ProductInfo>>,{
id?:number,
body:ToNumberOrNull<ProductBody>[],
test:ToNumberOrNull<ProductTest>,
}>
通过这样的转换 已经可以得到ProductInfoForView这个数据类型了,并且扩展性一定比Omit更好,快去试试吧