Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Enforce Plain HTML Element Passed as Children in Typescript

I’m trying to create a React component which enforces that its children are plain HTML elements (such as <p>...</p>) and not React components (such as <SomeComponent/>)

Here’s some code I’ve tried, to no avail

import React from "react"

interface ITooltipProps {
  // Goal is to require a plain HTML child here, i.e. <p>...</p>, and error if we get anything else
  // children: React.ReactElement<JSX.IntrinsicElements[keyof JSX.IntrinsicElements]>;

  // This doesn't work because the JSX.IntrinsicElements map just returns props, not the element type
  // children: JSX.IntrinsicElements[keyof JSX.IntrinsicElements];
  
  // This doesn't work because it's just asking for a react component that can take props of an HTML element (all of which are optional)
  children: React.ReactElement<JSX.IntrinsicElements[keyof JSX.IntrinsicElements]>;
}

export function Tooltip({
  children
}: ITooltipProps) {
  return (
    <div>
        {children}
    </div>
  )
}

// An element which doesn't return a plain HTML child
const F = () => {
  return (
    <>
        <p>Hello</p>
        <p>World</p>
    </>
  )
}

const x = (
    // Expect <F/> to error, since F isn't returning a plain HTML object / is returning a fragment
  <Tooltip>
    <F/>
  </Tooltip>
)

(Here’s a link to a TS playground with the above code)

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Am wondering if anybody knows how to enforce that a component’s children are "primitive" HTML elements, as opposed to react components – thanks!

>Solution :

This is not possible.

Rendered JSX has a return type of JSX.Element no matter what it contains. So plain html, a fragment, or a rendered component all have the same type. Which means you can’t use types to constrain it in this way.

See this playground

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading