I want to use a type (or interface) to extends a React component.
Definition:
type CoreProps<T> = {
htmlElement?: 'article' | 'aside' // ...
} & React.HTMLAttributes<T>
Usage desired:
type MyComponentProps = {
myComponentFirstProp: string
// ...
}
const MyComponent = ({
htmlElement,
myComponentFirstProp,
...props
}: MyComponentProps & CoreProps): JSX.Element => {
// ...
}
I know I can replace <T>
by HTMLElement
but is there a way to type CoreProps
according to the input htmlElement
passed in MyComponent
?
There is JSX.IntrinsicElements
type in which you can obtain relevant HTMLAttributes
, so you can do it in this way.
interface CoreProps<T> {
htmlElement: T;
}
interface MyComponentProps {
myComponentFirstProp?: string;
}
const MyComponent = <T extends keyof JSX.IntrinsicElements>(
props: CoreProps<T> & JSX.IntrinsicElements[T] & MyComponentProps
): JSX.Element => {
...
};
<MyComponent htmlElement="img" src="." />; // OK
<MyComponent htmlElement="a" href="." />; // OK
<MyComponent htmlElement="article" />; // OK
<MyComponent htmlElement="a" src="." />; // Error, no 'src' attribute in <a> element
If you want the corresponding type of attributes
import { DetailedHTMLFactory, ReactHTML } from 'react';
type EleAttributes<
T extends keyof ReactHTML
> = ReactHTML[T] extends DetailedHTMLFactory<infer R, infer P> ? R : never;
EleAttributes<'input'>
EleAttributes<'aside'>
...
Based your example:
type CoreProps<T extends keyof JSX.IntrinsicElements> = {
htmlElement?: T;
} & JSX.IntrinsicElements[T];
type ComponentProps = {
display?: string;
};
const Component = <T extends keyof JSX.IntrinsicElements>({
htmlElement,
display,
style,
children,
...props
}: ComponentProps & CoreProps<T>) => {
const styles = {
...style,
display,
// more ...
};
// Set default 'div' when htmlElement is undefined
return React.createElement(
htmlElement || 'div',
{
style: styles,
...props,
},
children
);
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.