qwik polymorphism
Even in Qwik you sometimes need more complex components that need to be rendered both as a link and as a button or whatever element.
QwikIntrinsicElements#
The type QwikIntrinsicElements is the base you should rely on here. The Qwik team has extended the HTMLAttributes here.
What can your props look like now? As the title suggests, we can't get around generics.
For my button component, the props look like this:
export type ButtonProps<C extends keyof QwikIntrinsicElements> =
QwikIntrinsicElements[C] & { as?: C;};
C is then the prop that decide what props are used from QwikIntrinsicElements.
The implementation for this is then altogether the following:
import type { QwikIntrinsicElements } from '@builder.io/qwik';import { component$, Slot } from '@builder.io/qwik';
export default component$( <C extends keyof QwikIntrinsicElements>(props: ButtonProps<C>) => { const Component = (props.as ?? 'button') as string; return ( <Component> <Slot /> </Component> ); });
export type ButtonProps<C extends keyof QwikIntrinsicElements> = QwikIntrinsicElements[C] & { as?: C; };
You are welcome to add your own props under as?
.
Casting as string#
const Component = (props.as ?? 'button') as string;
Unfortunately there seems to be no clean carry over for the key into JSX yet. I have experimented quite a bit and worked with keyof QwikIntrinsicElements
etc. I had first worked with any
, but since I'm sure many of you use Prettier and Lint, I find string a bit more appropriate here.
Much easier than in React, where you always have to think forwardRef
as well.
Have fun with Polymorphism