core
core copied to clipboard
TSX with dynamic element name results in "TS2322: Type '{ class: string; }' is not assignable to type 'ReservedProps'."
Version
3.2.31
Reproduction link
Steps to reproduce
Using Vue CLI create a Vue 3 + TS(X) project.
Create a component with the following where as
is a string prop:
render () {
const Element = this.as;
return (
<Element class={this.styles}>
{this.$slots.default && this.$slots.default()}
</Element>
);
},
What is expected?
That we can create an element tag dynamically based on a value
What is actually happening?
TS2322: Type '{ class: string; }' is not assignable to type 'ReservedProps'.
Property 'class' does not exist on type 'ReservedProps'.
228 |
229 | return (
> 230 | <Element class={this.styles}>
| ^^^^^
231 | {this.$slots.default && this.$slots.default()}
232 | </Element>
233 | );
I also tried to use <component is={this.as}
> which simply results in the literal value <component>
being rendered in the DOM. Trying <Component>
results in Cannot find name "Component"
. By the way, the SFC playground does not support TSX files.
@pikax can you take a look at this one? Thanks!
Just use lower-case element
instead of Element
.
@LinusBorg, I'm bumping this up.
When I use the lower-case approach suggested above, it actually works (with vite build, vitest and vue-loader) but then VS Code complains about a constant is declared but never used. It seems that this needs a proper solution instead of a workaround.
Version
3.2.31
Reproduction link
Steps to reproduce
Using Vue CLI create a Vue 3 + TS(X) project.
Create a component with the following where
as
is a string prop:render () { const Element = this.as; return ( <Element class={this.styles}> {this.$slots.default && this.$slots.default()} </Element> ); },
What is expected?
That we can create an element tag dynamically based on a value
What is actually happening?
TS2322: Type '{ class: string; }' is not assignable to type 'ReservedProps'. Property 'class' does not exist on type 'ReservedProps'. 228 | 229 | return ( > 230 | <Element class={this.styles}> | ^^^^^ 231 | {this.$slots.default && this.$slots.default()} 232 | </Element> 233 | );
I also tried to use
<component is={this.as}
> which simply results in the literal value<component>
being rendered in the DOM. Trying<Component>
results inCannot find name "Component"
. By the way, the SFC playground does not support TSX files.
const CustomComp = defineComponent({
name: "CustomComp",
setup(props) {
const HelloWord = defineComponent(() => {
return () => <span class="text-primary font-bold">HelloWord</span>
})
return () => (
<HelloWord class={['text-red']}></HelloWord>
)
}
});
This writing works for me, share with you