Is it possible to have generic children for a generic component?
I'm trying to create a type-safe form, with a generic component. I pass a generic type argument to the parent component and I want it's children to derive that generic type. Here's my attempt:
Form
is a generic component that receives MyForm
type parameter and should only accept such children which name
props of are keys of MyForm
. The above code errors out in few places. I know that traditionally children
should be of type JSX.Element
but Elements are not callable.
I remember having issues trying to do that in React, I'm not sure if it's possible8 Replies
I know I could do something like
<Input<MyForm> name="firstName" />
but that defeats the point, reallyI really hope I get proven wrong, but I am afraid this is not possible. The typing around jsx is very rudimentary, it's a typescript-thing. or can those be scoped 🤔 no they can't
also
const div = <div/>
for example also gives this general, undescriptive JSX.Element
and not a HTMLDivElement
. So there is no way afaik to type your JSX children in any meaningful way.
well, you could do const A = (props: {children: string}) => ...
and then <A><></></A>
would type-error, but that doesn't help you
I think maybe overwriting a declaration-file might be more suitable for what you are looking to do?
but then you would only be able to do it once in your project, which is also kind of awkward
const c = children(() => props.children);
is the right form, no need to call props.children
and typing children as JSX.Element
is correct. afaik Component
is just so u can write const C : Component<Props> = (props) => ...
instead of const C = (props: Props) => ...
i was tinkering around with it over at https://playground.solidjs.com/anonymous/018ead8b-9405-4823-a88e-27c2a5508b60
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
if u write solid the ugly hacky way there is a way u could get it typechecked. but as
JSX
it's considered invalid JSX
, so it will type-error.typescript can't typecheck what you're trying to do in your example, because it only sees the return type of
Input
and can't pass any information to the invocation of the component; it's like trying to do this:
looking at that you might be tempted to include the string in the return type of innerFn
and check that but functions invoked as jsx have their return types upcast to JSX.Element
by typescript, see https://github.com/microsoft/TypeScript/issues/21699
realistically the best you can do is check at runtime and throw an error if you want this to work in the format you want, but there are some other solutions, like passing a component with only valid props allowed:
personally i would just do a runtime check since you still have to guarantee that no names were used more than once, and all names were used
and typescript jsx definitely can't do thatThought as much, though I was hoping there is a way 😅 Thanks all for the dedication to answering this!! It was very insightful
don't know if its worth it but always kind of fun to type stuff with typescript, can do something like this, by passing children as a function instead of just JSX.
then you're a bit constrained you'll have to pass all components that you intend to use as arguments to render function but it types can be as you want really
I ended up doing exactly that, thanks!