React组件能否继承父组件泛型参数?以RcSelect为例
可行,通过封装自定义组件实现子组件继承父组件泛型参数
rc-select 默认的 Select 和 Select.Option 泛型是独立的,所以父组件指定的 ValueType 不会自动约束子 Option 的 value 类型,导致你遇到的类型校验失效问题。要实现子组件继承父组件泛型、自动校验 Option 的 value 类型,且支持动态渲染场景,你可以通过封装一层自定义组件来解决。
实现步骤
- 基于 rc-select 封装一个带泛型的自定义
Select组件,强制约束子元素必须是符合父组件泛型的Option:
import { Select as RcSelect } from 'rc-select'; import type { SelectProps, OptionProps } from 'rc-select'; import React from 'react'; // 自定义Select的Props,约束children为符合ValueType的Option元素/数组 type CustomSelectProps<ValueType> = SelectProps<ValueType> & { children: React.ReactElement<OptionProps<ValueType>> | React.ReactElement<OptionProps<ValueType>>[]; }; export const CustomSelect = <ValueType,>(props: CustomSelectProps<ValueType>) => { return <RcSelect<ValueType> {...props} />; }; // 挂载rc-select的Option到自定义Select上 CustomSelect.Option = RcSelect.Option;
- 使用自定义组件替代原生 rc-select:
type FooBar = 'Foo' | 'Bar'; // 此时Option的value会被自动约束为FooBar类型,传入"Bogus"会直接触发TypeScript报错 <CustomSelect<FooBar>> <CustomSelect.Option value="Foo">Foo</CustomSelect.Option> <CustomSelect.Option value="Bogus">Bogus</CustomSelect.Option> {/* TypeScript报错:类型"Bogus"不能赋值给类型"FooBar" */} </CustomSelect>
支持动态渲染场景
对于 map 生成的动态 Option,只要确保数据源的 value 类型符合父组件指定的泛型,就能自动完成校验:
// 数据源的value被约束为FooBar类型 const optionList: { value: FooBar; label: string }[] = [ { value: 'Foo', label: 'Foo' }, { value: 'Bar', label: 'Bar' }, // { value: 'Bogus', label: 'Bogus' } // 这里会直接报错,提前拦截问题 ]; <CustomSelect<FooBar>> {optionList.map(item => ( <CustomSelect.Option key={item.value} value={item.value}> {item.label} </CustomSelect.Option> ))} </CustomSelect>
原理说明
通过自定义组件的 CustomSelectProps,我们强制要求 children 必须是符合父组件 ValueType 泛型的 Option 元素。TypeScript 会自动校验每个子 Option 的 value 类型是否匹配父组件指定的泛型,无需手动给每个 Option 单独指定泛型,同时也能覆盖动态渲染的场景。
内容的提问来源于stack exchange,提问作者Svip
相关产品推荐
相关产品推荐

