简体   繁体   English

需要特定类型的功能组件作为带有 Typescript 的 React 中的道具

[英]Require a specific type of functional component as a prop in React with Typescript

Say you have a component tree like:假设您有一个组件树,例如:

 function Parent(props: { componentProp: ReactElement }) {
   return (
     <>
       {props.componentProp}
     </>
   );
 }

 function ChildA(props: { message: string }) { return (<h1>{props.message}</h1>) }
 function ChildB(props: { message: string }) { return (<h2>{props.message}</h2>) }

 function App() {
   return (
     <Parent componentProp={<ChildA message="hi"/>}
   );
 }

As written, you could replace ChildA with ChildB in componentProp and Typescript would not complain.如所写,您可以在componentProp中将ChildA替换为 ChildB 并且ChildB不会抱怨。

Is it possible to restrict the type of componentProp such that you could only pass ChildA , and passing ChildB would throw a type error?是否可以限制componentProp的类型,使您只能传递ChildA ,而传递ChildB会引发类型错误?

The type of any rendered JSX is always the same -- I don't know of any way to distinguish them.任何呈现的 JSX 的类型总是相同的——我不知道有什么方法可以区分它们。 Even if you do something like this, the rendered JSX type is unaffected by the function return type:即使你这样做,呈现的 JSX 类型也不受 function 返回类型的影响:

type Valid = ReactElement & { __valid: true }
function ChildA(props: { message: string }): Valid {
    const result = <h1>{props.message}</h1>
    return { ...result, __valid: true } // fails
}
const ca = <ChildA message="foo"/> // still ReactElement

However, you can distinguish the component functions themselves, and pass them as props instead of their rendered versions.但是,您可以区分组件函数本身,并将它们作为道具而不是渲染版本传递。 If the valid components have different props, then you can ride off that, otherwise you could add either a junk prop or a junk return object property:如果有效组件具有不同的道具,那么您可以摆脱它,否则您可以添加垃圾道具或垃圾返回 object 属性:

export default null
type Valid = (props: unknown) => ReactElement & { _valid: null }

// option 1:
const A = () => {
    const result = <></>
    return { ...result, _valid: null }
}

// option 2:
const B = (() => <></>) as unknown as Valid

const C = () => <></>

function Parent({ Child }: { Child: Valid }) {
    return <><Child /></>
}

function App() {
    return (
        <>
            <Parent Child={A} /> {/*passes*/}
            <Parent Child={B} /> {/*passes*/}
            <Parent Child={C} /> {/*fails*/}
        </>
    )
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM