我想实现这样的东西,以便可以推断Component
的类型,从而可以自动安全地键入props
。
type ComponentsType<T extends React.FC<any>> {
[key: string]: {
Component: T;
props?: React.ComponentProps<T>
};
}
const components: ComponentsType = {
RedButton: {
Component: Button,
props: { // <- this should be automatically typed to take props of Button
color: 'red'
}
},
BlueButton: {
Component: Button,
props: { // <- this should be automatically typed to take props of Button
color: 'blue'
}
},
FullWidthCard: {
Component: Card,
props: { // <- this should be automatically typed to take props of Card
variant: 'full-width'
}
},
}
但是上面的输入不起作用,因为泛型部分位于对象的根(AKAcomponents
)上,而不是位于每个属性(AKARedButton
或FullWidthCard
)上。
那么typescript有没有办法一个一个地遍历它们,一个一个地推断出组件呢?
感谢为了实现预期的行为,您需要从函数参数中推断出每个组件和道具。我的意思是,你需要创建一个额外的函数。
import React, { FC, ComponentProps } from 'react'
const Button: FC<{ color: string }> = (props) => null
const Card: FC<{ variant: string }> = (props) => null
type WithProps<T> =
T extends Record<infer Key, infer _> ? {
[P in Key]: T[Key] extends { Component: infer Comp, props: infer PassedProps }
? Comp extends React.JSXElementConstructor<infer Prps>
? { Component: Comp, props: ComponentProps<Comp> & Record<Exclude<keyof PassedProps, keyof Prps>, never> }
: never
: never
} : never
const components = <
Comp extends React.JSXElementConstructor<any>,
Item extends { Component: Comp },
Components extends Record<string, Item>>(dictionary: Components & WithProps<Components>) => {}
游乐场
Comp
-推断组件
Item
-推断字典项,component&props
对象
Components
-推断出整个参数
WithProps
-遍历传递参数的每个对象,并检查props
对象是否可分配给组件道具。如果是-返回道具,否则否定所有无效的道具到never
。
components({
RedButton: {
Component: Button,
props: {
color: 'red'
}
},
BlueButton: {
Component: Button,
props: {
extra_prop:42, // DRAWBACK, no error
color: 'blue'
}
},
FullWidthCard: {
Component: Card,
props: {
variant_invalid_prop: 'full-width' // expected error
}
},
})
但是有一个缺点,这个函数会接受额外的道具,比如extra_prop
。
注:我希望有人能提出更好的解决方案,额外的道具也将无效