Description
Describe the bug
Building Composable components is problematic with TypeScript. Slots used to work well, the new {@render ...}
method seems to cause some Type errors with Snippets/Component types 🤔
// Button.svelte file
<script lang="ts">
import type { Component } from 'svelte';
type ButtonProps = {
text?: string;
icon?: Component;
};
let {icon, text}:ButtonProps = $props()
</script>
<div class="content">
{#if icon}
{@render icon()}
{/if}
{text}
</div>
Above code snippet throws a type error:
/home/projects/svelte-render-component-type/src/lib/Button.svelte:14:14
Error: Argument of type '{ $on?(type: string, callback: (e: any) => void): () => void; $set?(props: Partial<{}>): void; }' is not assignable to parameter of type '{ '{@render ...} must be called with a Snippet': "import type { Snippet } from 'svelte'"; } & unique symbol'.
Property ''{@render ...} must be called with a Snippet'' is missing in type '{ $on?(type: string, callback: (e: any) => void): () => void; $set?(props: Partial<{}>): void; }' but required in type '{ '{@render ...} must be called with a Snippet': "import type { Snippet } from 'svelte'"; }'. (ts)
And if I update the type to use Snippets, it still throws an error, the error is now thrown in the parent component
// Button.svelte file
<script lang="ts">
import type { Snippet } from 'svelte';
type ButtonProps = {
text?: string;
icon?: Snippet;
};
let {icon, text}:ButtonProps = $props()
</script>
<div class="content">
{#if icon}
{@render icon()}
{/if}
{text}
</div>
// App.svelte file throws a type error
<Button text="I can accept props" icon={CustomIcon} />
The type error thrown is this:
/home/projects/svelte-render-component-type/src/App.svelte:11:39
Error: Type '__sveltets_2_IsomorphicComponent<{ [x: string]: never; }, { [evt: string]: CustomEvent; }, {}, {}, string>' is not assignable to type 'Snippet<[]>'.
Target signature provides too few arguments. Expected 2 or more, but got 0. (ts)
Previously in Svelte v4
I would just use <svelte:component this={icon} />
and it would work well.
Ref: https://svelte.dev/docs/svelte/v5-migration-guide#svelte:component-is-no-longer-necessary
Reproduction
Please fork and test this stackblitz project: https://stackblitz.com/edit/svelte-render-component-type?file=src%2Flib%2FButton.svelte
Steps:
- Access the terminal
- run
npm check
- you should see the type errors
Logs
System Info
~/projects/svelte-render-component-type 24s
❯ npx envinfo --system --npmPackages svelte,rollup,webpack --binaries --browsers
Need to install the following packages:
envinfo@7.14.0
Ok to proceed? (y) y
System:
OS: Linux 5.0 undefined
CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
Memory: 0 Bytes / 0 Bytes
Shell: 1.0 - /bin/jsh
Binaries:
Node: 18.20.3 - /usr/local/bin/node
Yarn: 1.22.19 - /usr/local/bin/yarn
npm: 10.2.3 - /usr/local/bin/npm
pnpm: 8.15.6 - /usr/local/bin/pnpm
npmPackages:
svelte: ^5.19.3 => 5.19.3
Severity
annoyance