Qwik Polymorphism

Tobias Zimmermann2 Minuten Lesezeit

Auch in Qwik braucht man machnmal komplexere Komponenten, die sowohl als Link als auch als Button oder welches Element auch immer gerendert werden müssen.

QwikIntrinsicElements#

Der Type QwikIntrinsicElements ist hier die Basis auf die du setzen solltest. Das Qwik-Team hat hier die HTMLAttributes erweitert.

Wie können jetzt deine Props aussehen? Wie der Titel schon vermuten lässt, kommen wir nicht um Generics herum.

Für meine Buttonkomponent sehen die Props so aus:

tsx
export type ButtonProps<C extends keyof QwikIntrinsicElements> =
QwikIntrinsicElements[C] & {
as?: C;
};

C ist dann die prop, die entscheiden, was für Props aus QwikIntrinsicElements verwendet werden.

Die Implementierung dafür ist dann insgesamt folgende:

tsx
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;
};

Gern kannst du unter as? einfach noch deine eigenen Props hinzufügen.

Casting als String#

tsx
const Component = (props.as ?? 'button') as string;

Leider scheint es noch kein sauberer Übertrag in JSX zu existieren. Ich habe relativ viel experimentiert und mit keyof QwikIntrinsicElements etc. gearbeitet. Ich hatte erst mit anygearbeitet, aber da viele von euch sicher Prettier und Lint nutzt, finde ich string hier etwas passender.

Viel einfacher als in React, wo man immer auch forwardRef mit denken muss.

Viel Spaß mit Polymorphism