sveltesvelte-5

Type for Components Passed as Props in Svelte 5


Let's say I have a parent component called SplitView.svelte:

<script lang="ts">
  import type { Snippet } from 'svelte'
  
  type Props = {
    master: Snippet
    detail: Snippet
  }
  let { master, detail }: Props = $props()
</script>

<div class="split">
  <div id="master">
    {@render master()}
  </div>
  <div id="detail">
    {@render detail()}
  </div>
</div>

Which I use elsewhere like this:

<script lang="ts">
  import SplitView from '$lib/components/shared/SplitView.svelte'
  import Master from './master/PricingMaster.svelte'
  import Detail from './detail/PricingDetail.svelte'
</script>

<SplitView master={Master} detail={Detail} /> <-- ESLint error

I'm getting a linter error on the master and detail attributes:

Type '__sveltets_2_IsomorphicComponent<Record<string, never>, 
{ [evt: string]: CustomEvent<any>; }, {}, {}, string>' is not assignable to type 'Snippet<[]>'.

Target signature provides too few arguments. Expected 2 or more, but got 0.ts(2322)

Are components sent as props not of type Snippet? What am I doing wrong?


Solution

  • The type for components should be Component in Svelte 5, and you just pass it down with a capital first letter so you can directly render it on your SplitView:

    //SplitView.svelte
    <script lang="ts">
      import type { Component } from 'svelte'
    
        type Props = {
        Master: Component
        Detail: Component
      }
      
      let { Master, Detail }= $props()
    </script>
    
    <div class="split">
      <div id="master">
            <Master />
      </div>
      <div id="detail">
            <Detail />
      </div>
    </div>
    

    and use like this:

    <script lang="ts">
      import SplitView from './SplitView.svelte'
      import MyMaster from './PricingMaster.svelte'
      import Detail from './PricingDetail.svelte'
    
      // Name your components, Master and Detail to simplify the Props
    </script>
      <!-- or use Master={MasterName} Detail={DetailName} 
      to pass components with different component names -->
    <SplitView Master={MyMaster} {Detail} />