React+TypeScript中传入字符串HTML标签时如何正确定义类型
类型安全的动态标签React组件实现
原写法的问题在于将tag标注为普通string类型、统一使用HTMLElement的属性定义,无法根据传入的标签名自动匹配对应标签的专属属性,丢失了TS类型校验能力。最简洁规范的实现方式是通过React内置类型工具配合泛型完成自动类型推导,不需要手动维护标签与属性的映射关系。
实现代码
import React, { ElementType, ComponentPropsWithoutRef } from 'react' import c from 'classnames' import styles from './index.module.css' export type ComponentProps<T extends ElementType = 'div'> = ComponentPropsWithoutRef<T> & { tag?: T } function Component<T extends ElementType = 'div'>({ className, tag, children, ...restProps }: ComponentProps<T>) { const Element = tag || 'div' return ( <Element className={c(className, styles.v)} {...restProps} > {children} </Element> ) } export default Component
实现效果
- 传入
tag="a"时,TS会自动校验<a>标签的专属属性(如href、target、rel等),传入非法属性或类型错误会直接抛出类型提示 - 传入
tag="input"时,会自动匹配输入框的原生属性(如type、value、onChange等) - 未传入
tag时,默认按div标签的属性规则做校验 - 所有原生事件、ARIA属性、自定义透传属性都会被正确识别,不会丢失类型提示
关键类型说明
ElementType是React内置的类型,涵盖了所有合法的原生HTML标签字符串、以及合法的React组件类型,作为泛型约束可以避免传入非法的tag值ComponentPropsWithoutRef会自动根据传入的标签/组件类型,推导对应的全部原生属性,自动排除ref属性(如果需要支持ref可以换成ComponentPropsWithRef,配合forwardRef包装即可)- 泛型默认值设为
'div',和组件的默认tag逻辑对齐,避免无tag传入时出现类型错误
内容的提问来源于stack exchange,提问作者Lance Pollard
相关产品推荐
相关产品推荐

