9

I would like to use a dynamic component to select a view depending on the value of an enum:

<svelte:component
  this={components[enumValue]}
  {...props}
/>

But I don't get a compile error if I don't pass all the necessary parameters:

<svelte:component
  this={components[enumValue]}
/>

How to correctly specify the typing of dynamic components?


UPD: map example with React

const props: Props = {...}
const components: Record<EnumType, React.FC<Props>> = {
  [EnumType.variant_1]: Component1,
  [EnumType.variant_2]: Component2,
}

1 Answer 1

14

You can apply a little indirection using a generic wrapper component. E.g.

<!-- renderer.svelte -->
<script lang="ts" generics="C extends ComponentType">
    import type { ComponentType, ComponentProps } from 'svelte';

    export let component: C;
    export let props: ComponentProps<InstanceType<C>>;
</script>

<svelte:component this={component} {...props} />

Usage example:

<!-- adder.svelte -->
<script lang="ts">
    export let a: number;
    export let b: number;
</script>

{a} + {b} = {a + b}
<script lang="ts">
    import Renderer from './renderer.svelte';
    import Adder from './adder.svelte';
</script>

<Renderer component={Adder} />
<!-- Error on "Renderer" because props are missing -->

<Renderer component={Adder} props={{ a: 12 }} />
<!-- Error on "props": Property 'b' is missing in type '{ a: number; }'
                       but required in type '{ a: number; b: number; }' -->

This may require very recent versions of svelte/svelte-preprocess to work correctly with the generics. You could also drop the generics and type the renderer's properties more loosely. Having props as an export of another component at the very least ensures the props missing error.

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks, your example works! To solve my problem, it remains to get the components type with the desired type of parameters. For example, in React it can be solved with React.FC type like in UPD. I can't find any example how to get Svelte component type.
Also, I don't understand how to use keywords "bind", "on", "use" in this case
You probably will not be able to use every feature when doing something like this. You will not be able to use bind in any case, if you spread properties. In general using svelte:component should be a rare occurrence, so you should pick your trade-offs. What is UPD? Also, you already have the "component type", it is what you import from a Svelte file.
If you want to get the type from within a component, that is currently not supported (GitHub issue).
@Einar: I updated the answer to reflex current syntax/types.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.