Calcimicium
Calcimicium

Reputation: 115

React TypeScript prevent element having children of unexpected type

I'd like to prevent a react component having at least (one or more) children of a specific type.

This script works, but it allows the component having other types of children, except primitive ones:

import * as React    from "react"

class App extends React.Component {
    render() {
        return <div>
            {/* Should compile, it does: OK! */}
            <Foo><Bar lorem={0} /></Foo>

            {/* Should compile, it does: OK! */}
            <Foo>
                <Bar lorem={1} />
                <Bar lorem={2} />
            </Foo>

            {/* Should not compile, it does not: OK! */}
            <Foo />

            {/* Should not compile, it does: NOT OK... */}
            <Foo><div /></Foo>

            {/* Should not compile, it does: NOT OK... */}
            <Foo>
                <div />
                <div />
            </Foo>
        </div>
    }
}

class Foo extends React.Component<FooProps> {
  render() {
    return <ul>{this.props.children}</ul>
  }
}

interface FooProps {
    children: React.ReactElement<BarProps> | React.ReactElement<BarProps>[]
}

class Bar extends React.Component<BarProps> {
    render() {
        return <li>{this.props.lorem}</li>
    }
}

interface BarProps {
    lorem: number
}

Is there something wrong with my code ?

You can download a Git short project here to try it.

Thanks

Upvotes: 0

Views: 1843

Answers (1)

Tomasz Białecki
Tomasz Białecki

Reputation: 1111

According to the documentation you cannot retrieve type information from JSX.Element

The JSX result type
By default the result of a JSX expression is typed as any. You can customize the type by specifying the JSX.Element interface. However, it is not possible to retrieve type information about the element, attributes or children of the JSX from this interface. It is a black box.

By overriding children type definition you can limit the type to string for example or single JSX.Element, any custom component will be 'casted' to JSX.Element and its type is not accessible.

The JSX result type

Upvotes: 1

Related Questions