如何在React中为Lit泛型Web Component传递泛型类型?
解决React封装泛型Lit Web Component的类型传递问题
问题描述
我有一个用Lit编写的Web Component,它的value属性和自定义事件使用了泛型类型:
@customElement('bl-select') export default class BlSelect<ValueType extends FormValue = string> extends FormControlMixin(LitElement) {
我无法在React中传递这个泛型类型,当前的封装代码如下:
export const BlSelect = React.lazy<ReactWebComponent<BlSelectType, { onBlSelect: EventName<CustomEvent<ISelectOption<ValueType>[]>> }>>(() => customElements.whenDefined('bl-select').then(elem => ({ default: createComponent<BlSelectType>( { react: React, tagName: 'bl-select', elementClass: elem, events: {"onBlSelect":"bl-select"} } ) }) ));
上述代码中的ValueType没有实际作用,我需要让使用这个React封装组件BlSelect的开发者能够传入泛型类型,请问该怎么做?
解决方案
要让React封装的组件支持泛型类型传递,你需要将导出的React组件声明为泛型函数,并关联value属性和事件的类型到泛型参数:
定义泛型Props类型
首先创建一个泛型的Props类型,将ValueType作为泛型参数,确保value属性和onBlSelect事件的类型都依赖于这个参数:import { ReactWebComponent, EventName } from '@lit/react'; import type BlSelect from './path/to/bl-select'; import type { FormValue, ISelectOption } from './path/to/types'; // 定义泛型的React组件Props type BlSelectReactProps<ValueType extends FormValue = string> = ReactWebComponent< // 覆盖原组件的value属性类型 Omit<InstanceType<typeof BlSelect<ValueType>>, 'value'> & { value?: ValueType }, { // 让事件回调的参数类型关联到ValueType onBlSelect: EventName<CustomEvent<ISelectOption<ValueType>[]>> } >;声明泛型React组件
将导出的BlSelect组件声明为泛型函数,这样使用者在调用时可以指定ValueType:export const BlSelect: <ValueType extends FormValue = string>( props: BlSelectReactProps<ValueType> ) => React.ReactElement = React.lazy(() => customElements.whenDefined('bl-select').then((elem) => ({ default: createComponent({ react: React, tagName: 'bl-select', elementClass: elem, events: { "onBlSelect": "bl-select" } }) })) );使用者如何使用
现在其他开发者可以在使用组件时指定泛型类型,获得完整的类型提示:// 示例:使用number类型作为ValueType <BlSelect<number> value={100} onBlSelect={(e) => { // e.detail 会被自动推断为 ISelectOption<number>[] console.log(e.detail[0].value); // 类型为number }} />
关键说明
- 通过将导出的组件声明为泛型函数,TypeScript可以在使用者指定泛型参数时,自动推导
value属性和事件回调的类型。 - 使用
Omit和类型交叉来覆盖原Web Component的value属性类型,确保和泛型参数保持一致。 - 无需修改原Lit组件的代码,仅需在React封装层处理泛型类型的传递。
内容的提问来源于stack exchange,提问作者Murat Çorlu
相关产品推荐
相关产品推荐

