我正在创建一个名为text的React组件,该组件允许更改将要呈现的标签。
export interface TextProps extends HTMLAttributes<HTMLElement> {
children: ReactNode;
as?: React.ElementType;
}
问题是,我试图使用这样的time
元素:
<Text as="time" dateTime="2018-07-07">
July 7
</Text>
但是TS编译器抱怨Property 'dateTime' does not exist on type 'IntrinsicAttributes & TextProps'
我甚至尝试使用interface TextProps extends HTMLAttributes<HTMLTimeElement>
,但我仍然得到相同的错误。
老实说,我不知道如何在这种组件上实现类型安全
如果你想让as
支持任何内置的HTML元素,我们可以使用JSX.IntrinsicElements
接口,它将HTML标签名称映射到它们的道具。
type IntrinsicProps = {
[K in keyof JSX.IntrinsicElements]: JSX.IntrinsicElements[K] & { as: K; }
}[keyof JSX.IntrinsicElements]
此映射类型IntrinsicProps
提供了props和as
的所有有效配对的联合。如果没有提供可选的as
道具,我们需要添加更多的道具类型。这取决于你使用的默认标签。
type TextProps = IntrinsicProps | ( HTMLAttributes<HTMLElement> & { as?: never } )
你可以将children
添加到道具中,也可以使用React.FC
自动添加children
。
const Text: React.FC<TextProps> = (props) => {
/* ... */
}
现在你可以添加dateTime
作为道具,但只有当你的as
类型支持它!
如此:
<Text as="time" dateTime="2018-07-07">July 7</Text>
但是这会给出一个错误"Property'dateTime'
does not exist on typeIntrinsicAttributes & ClassAttributes<HTMLDivElement> & HTMLAttributes<HTMLDivElement> & { ...; } & { ...; }
">
<Text as="div" dateTime="2018-07-07">July 7</Text>
Typescript Playground Link
试试React.TimeHTMLAttributes
type
export interface TextProps extends React.TimeHTMLAttributes<HTMLElement> {
children: ReactNode;
as?: React.ElementType;
}