我正在尝试定义通过 prop 接受 React.Context 字段的可重用 React 组件。它们可能不需要父上下文中可用的全部属性,并且考虑到重用的愿望,可以封装在具有不同上下文结构的提供者中(但重用子组件所需的核心属性相同)。例如,树中更高的父提供者可以像这样定义 Context 类型:type SuperSet = { x: number, y: number, z: number}let superSet = {x: 1, y: 2, z: 3}const SuperSetContext = React.createContext<SuperSet>(superSet)const SuperSetProvider = (props) => { return ( <SuperSetContext.Provider value={superSet}> ... {/* Arbitrarily deep nested component in the tree, most likely in a different file*/} <SubComponent Context={SuperSetContext} /> </SuperSetContext.Provider> );}SubComponent 应该(我相信)能够像这样定义一个具有较少属性的 Context Prop const SubComponent: React.FunctionComponent<{ Context: React.Context<{x: number, y: number}>}> = ({ Context }) => { const { x, y } = useContext(props./Context); return (<div>{x + y}</div>)}或者通过 PickContext: React.Context<Pick<SuperSet, 'x' | 'y'>>但是,无论哪种方式,当在 Provider 中分配 prop 时,上述 SubComponent 都会导致类型错误<SubComponent Context={SuperSetContext} />Type 'Context<SuperSet>' is not assignable to type 'Context<SubSet>'. Types of property 'Provider' are incompatible. Type 'Provider<SuperSet>' is not assignable to type 'Provider<SubSet>'. Types of parameters 'props' and 'props' are incompatible. Type 'ProviderProps<SubSet>' is not assignable to type 'ProviderProps<SuperSet>'.ts(2322)test.tsx(26, 3): The expected type comes from property 'Context' which is declared here on type 'IntrinsicAttributes & { Context: Context<SubSet>; } & { children?: ReactNode; }'我创建了一个 Typescript Playground 在没有 jsx 的情况下测试它,但无论使用 jsx 都会发生。另外,我没有看到与朴素的通用类/函数相同的行为。那么有没有一种方法可以使用子集或上下文属性 或 来定义子组件的上下文定义,以实现相同的设计并避免这种特定的类型不匹配? 最佳答案 在这种情况下,您应该使用通用组件 ( SubComponent ),因为 TS 就在这里:您不能假设 React.Context<SubSet> 是 React.Context<SuperSet> 的子集,因为它们是装箱类型。使用一个简单的通用组件,您可以解决这个问题,指定您真正想要的内容:上下文 类型 应该是一个子集:function SubComponent<T extends { x: number, y: number }>(props: { context: React.Context<T>}) { const { x, y } = React.useContext(props.context); return (<div>{x + y}</div>)}您可以在 Playground 中看到完整示例:Playground Link关于javascript - 如何键入接受具有超集属性的 Context 的 Typescript React 组件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/61242125/
10-16 19:26