reactjs - Typescript 根据变量动态分配泛型类型
问题描述
我想使用类型(或接口)来扩展 React 组件。
定义 :
type CoreProps<T> = {
htmlElement?: 'article' | 'aside' // ...
} & React.HTMLAttributes<T>
所需用途:
type MyComponentProps = {
myComponentFirstProp: string
// ...
}
const MyComponent = ({
htmlElement,
myComponentFirstProp,
...props
}: MyComponentProps & CoreProps): JSX.Element => {
// ...
}
我知道我可以替换<T>
为,HTMLElement
但有没有办法CoreProps
根据htmlElement
传入的输入进行输入MyComponent
?
解决方案
JSX.IntrinsicElements
您可以在其中获取相关的类型HTMLAttributes
,因此您可以通过这种方式进行操作。
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
如果你想要对应类型的属性
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'>
...
更新
根据您的示例:
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
);
};
推荐阅读
- c# - 如何使用 C# 在单元测试中模拟 Redis 超时
- javascript - Neo4j 驱动程序:无法读取未定义的属性“驱动程序”
- c# - 如何转换 ObservableCollection
返回 ObservableCollection ? - javascript - 当我运行 nodemon 服务器时,我收到错误“bad auth Authentication failed. [nodemon] app crashed - waiting for file changes before start...”
- javascript - Chrome 扩展:如何正确地将脚本添加到 popup.html 并使用 localStorage
- c++ - CMake意外地将最后一个文件名添加到foreach中的可执行文件中
- drupal - 在 Drupal8 中组织大量图像的最佳解决方案是什么?
- kotlin - 使用来自 github 的依赖项执行 kotlin -script.kts
- c# - 如何在 nancy 模块一侧保留成员变量或属性?
- java - ListItem 没有响应 Android 中 ArrayAdapter 中的 clickEvents?