React TypeScript包装组件类型定义两大疑问咨询
TypeScript React 包装组件类型问题解答
先看你提供的代码:
import React, { ReactNode, InputHTMLAttributes } from "react" type WrapperProps<P extends object> = { title: string children: (props: P) => ReactNode } & P const Wrapper = <P extends object>({ title, children, ...rest }: WrapperProps<P>) => { return children(rest) } type InputProps = { type: string, name: string } const WrappedInput = (inputProps: InputProps) => <Wrapper title="Hello, World" {...inputProps} >{(props) => <input {...props} />} </Wrapper>
问题1:children(rest)的类型不兼容提示根源
TypeScript的这个提示,本质是交叉类型解构后的类型推导和泛型P存在潜在冲突:
WrapperProps<P>是{title: string; children: (p:P)=>ReactNode}与P的交叉类型。当你解构出...rest时,TypeScript认为rest的类型是Omit<WrapperProps<P>, 'title' | 'children'>,而非直接等价于P。- 核心矛盾在于:TypeScript无法保证
P本身不包含title或children属性。如果P被实例化为包含这两个属性的类型(比如P = {title: number; name: string}),WrapperProps<P>中title的类型会变成string & number(即never),解构后的rest会包含这个never类型的title,但P本身的title是number,此时rest无法赋值给P,导致类型不兼容。
简单来说,TypeScript考虑了极端情况:如果有人故意让P包含title/children,代码会出问题,因此抛出提示。实际业务中你不会把这两个属性放进P,所以用rest as P强制转换是可行的。
问题2:children函数的props被错误推断包含title和children
这是因为TypeScript在推断Wrapper的泛型P时,错误地把传入Wrapper的所有属性都合并进了P:
- 你给
Wrapper传了title、inputProps(type/name)、还有children函数,TypeScript为了让WrapperProps<P>匹配传入的属性类型,会自动把这些属性全部合并到P里,导致P被推断成InputProps & {title: string; children: (props: ...)=>ReactNode},所以children函数的props就带上了这两个属性。
解决方法很直接:显式指定Wrapper的泛型P为InputProps,避免TypeScript自动错误推断:
const WrappedInput = (inputProps: InputProps) => <Wrapper<InputProps> title="Hello, World" {...inputProps} >{(props) => <input {...props} />} </Wrapper>
内容的提问来源于stack exchange,提问作者user1032752
相关产品推荐
相关产品推荐

