持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情
本篇文章结合开发遇到问题来讲解Typescript中如何获取ValueOf
回顾:keyof是什么怎么用
字面量类型(Literal Type)
要理解keyof首先搞搞明白字面量类型,字面量类型在ts中比较特殊,string,boolean, number 特殊主要体现在,
type a = 'hellow'
interface Config {
a :'hello' | 'world' | 'lalala';
isEnable: true;
margin: 0 | 2 | 4;
}
Config.a为"hello" | "world" | "lalala"
hello是string。
但是string不是hello
hello只是string里面的一个。
Config.a中的类型就是"hello" 或者"world" 或者 "lalala" 三个类型
Config.isEnable: true
类型就是true,只能为true类型
Config.margin: 0 | 2 | 4
类型就是0,2,4属于number但是只能是0或者2或者4
keyof
keyof T将会得到一个T中的的属性名(key)组成的联合字面量类型,这些属性名都属于string类型
type Type1Props = {
name: string
age: number
weight: number
...
}
type Type2Props = {
align: string
value: string
...
}
type Type3Props = {
align: string
value: string
...
}
interface ComTypes: {
Type1 : Type1Props,
Type2 : Type2Props,
Type2 : Type3Props,
}
type KeyComType = keyof ComTypes //'Type1' | 'Type2' | 'Type3'
如上 KeyComType最终得到的是ComTypes的所有key组成的联合类型 'Type1' | 'Type2' | 'Type3'
let newTypeObject: KeyComType
newTypeObject = "Type1" // OK
newTypeObject = "Type2" // OK
newTypeObject = "Type3" // OK
newTypeObject = "test" // `Error...`
ValueOf如何实现。
猜想interface的定义是不是就是对象呢,我们能不能通过key获取到value呢 c试试
interface ComTypes: {
Type1 : Type1Props,
Type2 : Type2Props,
Type3 : Type3Props,
}
type B = ComTypes['Type1'] 通过提示果然得到了我们想要的类型 Type1Props
那么valueof是不是可以通过
type ValueComTypes = ComTypes['Type1'] | ComTypes['Type2'] | ComTypes['Type3']
// Type1Props | Type2Props | Type3Props
我们惊奇的发现,keyof获取的是string类型的子类组成的联合类型。但是valueof获取的却是实实在在的类型,
不是string的子类是不是很不错。
也可以简写为
type ValueComTypes = ComTypes['Type1' | 'Type2' | 'Type3']
继续简化
type ValueComTypes = ComTypes[keyof ComTypes]
于是得到了ValueOf的 **通用泛型表达式**
type ValueOf<T> = T[keyof T];
后面我们使用可以直接
type ValueComTypes = ValueOf<ComTypes>
至此我们的通用ValueOf方法完成
实践
上一篇文章中我们介绍了组件动态化,于是在动态化过程中对不同组件设置不同Props就成了一个问题
需求
根据type值限定componentProps的类型必须为type对应的类型
如type === Type1 则componentProps为Type1Props
具体实现
Page.tsx
const Page = () => {
return (
<AComponent itemsArray = {[
{type: 'Type1', componentProps:{
name: 'jack',
age: 20,
weight: 60}
},
{type: 'Type2' componentProps: {
align: 'left',
value: '23'
}},
{type: 'Type3' componentProps: {
wight: 100,
length: '200'
}},
]}/>
)
}
export default Page
AComponent.tsx
interface ComTypes: {
Type1 : Type1Props,
Type2 : Type2Props,
Type3 : Type3Props,
}
type ItemType = keyof ComTypes
// T必须为Type1或者Type2或者Type3
type ItemProps<T extends ItemType> = {
type: T
componentProps?: ComTypes[T]// 根据T获取ComTypes中对应的TypeProps
showItem?: boolean
}
// 遍历得到
//{'Type1':ItemProps<'Type1'>, 'Type2':ItemProps<'Type2'>, 'Type3':ItemProps<'Type3'> }
type AntPropsMap = {
[u in ItemType]: ItemProps<u>
}
//调用前面定义的通用ValuesOf方法 获取所有values
type ItemArrayType = ValuesOf<AntPropsMap>
// 得到最终的组件props对应的类型
interface AComponentProps {
itemsArray: ItemArrayType[]
}
const AComponent: FC<AComponentProps> = ({itemsArray}) => {
}
export default AComponent
总结
根据我们一步步推到得到最终通用ValueOf方法为
type ValueOf<T> = T[keyof T];
并且得到的最终value组合类型为实实在在的类型,并非keyof那样获取到的是string的子类型。