jsx-vue2
jsx-vue2 copied to clipboard
Functional Components with TypeScript
HI!✌
I have 2 components. The first looks like this:
import { RenderContext, VNode } from 'vue';
import './BaseTitle.sass';
export interface IBaseTitleProps {
level: number;
}
export const BaseTitle = (context: RenderContext<IBaseTitleProps>): VNode => {
const { level } = context.props;
const HeadingComponent = `h${level}`;
return (
<HeadingComponent
class={`title base-title base-title_level-${level} ${context.data.staticClass || ''} ${context.data.class ||
''}`}>
{context.children}
</HeadingComponent>
);
};
And the second one:
import { VueComponent } from 'types/vue-components';
import { Component } from 'nuxt-property-decorator';
import { VNode } from 'vue';
import { BaseTitle } from 'components/base/BaseTitle';
@Component({
name: 'TheHeader',
})
export default class TheHeader extends VueComponent {
public render(): VNode {
return (
<header class='page-header'>
<BaseTitle level={4}>Page title</BaseTitle>
</header>
);
}
}
I get an error when I pass the prop level
there.
TS2322: Type '{ level: number; }' is not assignable to type 'RenderContext<IBaseTitleProps>'. Property 'level' does not exist on type 'RenderContext<IBaseTitleProps>'.
RenderContext
interface.
export interface RenderContext<Props=DefaultProps> {
props: Props;
children: VNode[];
slots(): any;
data: VNodeData;
parent: Vue;
listeners: { [key: string]: Function | Function[] };
scopedSlots: { [key: string]: NormalizedScopedSlot };
injections: any
}
I can rewrite it to something like this
<BaseTitle
props={{
level: 4,
}}
/>
but it also requires me to pass all other fields from RenderContext
interface
How to properly use functional components and TypeScript? Is there any example? Thanks.