如何为返回单个函数作为子元素的React组件进行TypeScript类型定义?
如何为接受函数作为子元素的React组件定义TypeScript类型
当然可以实现!你想要的是让TypeScript自动识别组件的children是一个特定类型的函数,并且在使用组件时自动补全这个函数的参数props,不用手动标注类型。下面是具体的实现方法:
1. 定义精确的组件Props类型
首先,我们需要明确组件的children属性类型,而不是依赖React.FC默认的ReactNode(它包含了所有可能的子元素类型,不够精确)。
以你的基础Component为例:
// 定义子函数接收的props类型 interface ComponentChildrenProps { someProp: string; } // 定义组件的Props类型,明确children是一个函数 interface ComponentProps { children: (props: ComponentChildrenProps) => React.ReactNode; } // 定义组件,不再使用React.FC,直接指定props类型 const Component = ({ children }: ComponentProps): JSX.Element => { const propsForChildren: ComponentChildrenProps = { someProp: "test" }; // 这里不需要再断言children是函数,TypeScript已经知道它的类型了 return <div>{children(propsForChildren)}</div>; };
2. 应用到你的表单组件场景
对于你的Form组件,我们可以用同样的方式改造,同时保留原有业务逻辑:
// 定义子函数接收的表单相关props interface FormChildrenProps { control: ReturnType<typeof useForm>["control"]; watch: ReturnType<typeof useForm>["watch"]; formState: ReturnType<typeof useForm>["formState"]; } // 定义Form组件的Props类型,包含业务需要的其他属性 interface FormProps { id?: string; onValidSubmit: (data: any) => void; // 明确children是接收FormChildrenProps的函数 children: (props: FormChildrenProps) => React.ReactNode; } // 实现Form组件 const Form = ({ id, onValidSubmit, children }: FormProps): JSX.Element => { const { handleSubmit, control, watch, formState } = useForm(); return ( <form id={id} onSubmit={handleSubmit(onValidSubmit)}> {/* 直接调用children,TypeScript会自动验证参数类型 */} {children({ control, formState, watch })} </form> ); };
3. 使用组件时的自动补全效果
现在当你使用Form组件时,TypeScript会自动识别children是一个函数,并且自动补全函数的参数props,不需要手动标注FormChildrenProps:
<Form onValidSubmit={(data) => console.log(data)}> {/* 这里的参数会自动提示control、watch、formState,不用手动写类型 */} {({ control, watch }) => ( <section> <TextField control={control} label="foo" name="foo" /> <TextField control={control} label="bar" name="bar" /> </section> )} </Form>
为什么不使用React.FC?
React.FC的children属性默认被定义为React.ReactNode,它包含了字符串、JSX元素、数组、null等多种类型,无法精确限制为我们需要的函数类型。通过手动定义ComponentProps中的children类型,我们可以让TypeScript强制执行子元素必须是指定的函数,同时提供完整的类型提示。
内容的提问来源于stack exchange,提问作者ChronicLogic
相关产品推荐
相关产品推荐

