Subscribe on changes!

types: Component cannot be rendered with JSX

avatar
Feb 11th 2021

Version

3.0.5

Reproduction link

https://codesandbox.io/s/boring-babbage-lgpd9?file=/src/main.tsx

Steps to reproduce

Try to compile declare const Foo: Component; return <Foo />

What is expected?

No errors. <Bar /> should complain about a missing id prop.

What is actually happening?

JSX element type 'Foo' does not have any construct or call signatures


This was broken with h(Foo) too until #3219

avatar
Feb 12th 2021

Why not use defineComponent?

avatar
Feb 13th 2021

It's a component passed in to a function from the user. The DefineComponent type mangles required prop types by passing them through ExtractPropTypes again. Component uses ComponentPublicInstanceConstructor which isn't exported. I basically need FunctionalComponent<Props> | ComponentPublicInstanceConstructor<Props>

Update: { new (): ComponentPublicInstance<Props> } | FunctionalComponent<Props> seems to do what I want.

avatar
Feb 15th 2021

I mean use defineComponent to create components

const Comp = defineComponent({ /* ... */ })

Comp always conforms to the use in TSX

avatar
Feb 15th 2021

We do, this is for a config that people can pass components into:

new Vuetify({
  iconSets: {
    fa5: FontAwesomeIcon
  }
})

I need a type that both:

  • Accepts components of any type (functional or defineComponent)
  • Lets me render that component (<options.iconSets.fa5 />)

use defineComponent to create components

Again I'm not the one creating these components, but defineComponent doesn't allow functional components. If you pass it a function it turns it into setup instead.

I ended up using { new (): ComponentPublicInstance<Props> } | FunctionalComponent<Props> for this but I'd expect the builtin Component type to just work without any messing around.

avatar
Feb 16th 2021

I got your point

avatar
Feb 17th 2021

This is a tricky one, Component should be the most generic valid component type.

TSX requires a type with a constructor to be able to render, which causes problems because Component does not require a constructor, because {} is a valid vue component.

There's no good solution for this, I think the Component is the wrong type to be used with TSX don't know if adding a new type is ideal, but this would probably work:

type ComponentTSX<Props = {}> = Component<Props> & { new (): ComponentPublicInstance<Props> }

declare const Foo: ComponentTSX;
declare const Bar: ComponentTSX<{ id: string }>;

() => [<Foo />, <Foo id="ok" />, <Bar id="ok" />];
avatar
Feb 17th 2021

I think with that you can't do const Foo: ComponentTSX = props => h(...