React TypeScript组件Props类型适配:如何让rest兼容所有子组件?
解决方案
首先修正你代码里的两处明显问题:
- Props类型缺少
title字段,但组件中使用了这个变量 - 组件参数解构时,应该提取
collectionName而非title(否则无法使用collectionName做判断)
接下来要让rest兼容三个子组件的Props,核心思路是让组件Props类型包含自身必填字段 + 三个子组件Props的联合类型,具体实现如下:
- 提取子组件的Props类型
使用React.ComponentProps工具类型可以直接获取任意React组件的Props类型:
import React from 'react'; // 假设这三个组件已经导入 import { TitlePlaceHolder, Heading, Text } from './your-components-path'; // 提取三个子组件的Props类型 type TitlePlaceHolderProps = React.ComponentProps<typeof TitlePlaceHolder>; type HeadingProps = React.ComponentProps<typeof Heading>; type TextProps = React.ComponentProps<typeof Text>;
- 定义CollectionName组件的完整Props类型
将自身必填的collectionName、title与三个子组件的Props联合类型做交叉:
type CollectionNameProps = { collectionName: string; title: string; } & (TitlePlaceHolderProps | HeadingProps | TextProps);
- 优化组件逻辑与类型窄化
为了让TypeScript准确识别rest对应的子组件类型,添加类型守卫函数实现类型窄化,避免类型断言:
// 类型守卫:判断rest是否为HeadingProps类型 function isHeadingProps( rest: TitlePlaceHolderProps | HeadingProps | TextProps ): rest is HeadingProps { return 'heading' in rest; } export const CollectionName = ({ collectionName, title, ...rest }: CollectionNameProps) => { if (!collectionName || collectionName === 'null') { return <TitlePlaceHolder {...rest} />; } if (isHeadingProps(rest)) { return <Heading {...rest}>{title}</Heading>; } return <Text fontSize="xs" color="textlight.tertiary" {...rest}>{title}</Text>; };
补充说明
- 如果
Text组件的fontSize和color是固定值,不希望被rest覆盖,可以把这两个属性从TextProps中排除,修改CollectionNameProps为:
type CollectionNameProps = { collectionName: string; title: string; } & (TitlePlaceHolderProps | HeadingProps | Omit<TextProps, 'fontSize' | 'color'>);
- 若三个子组件有共同的Props字段,联合类型会自动保留这些字段的兼容类型,无需额外处理。
内容的提问来源于stack exchange,提问作者Andon Mitev
相关产品推荐
相关产品推荐

