Open fritz-c opened 1 year ago
I stumbled upon this myself. I'll explain my case.
The following code works, even with the commented lines uncommented.
<script lang="ts" context="module">
export type NodeItem<T extends NodeItem<T>> = {
id: number;
text: string;
nodes?: T[];
}
</script>
<script lang="ts" generics="TItem extends NodeItem<TItem>">
export let nodes: TItem[];
$: console.log('Nodes: %o', nodes);
$: console.log('Slots: %o', $$slots);
</script>
<ul>
{#each nodes as node (node.id)}
<li>
<slot {node}>
<span>{node.text}</span>
</slot>
{#if (node?.nodes?.length ?? 0) > 0}
<svelte:self nodes={node.nodes} let:node={subNode}>
<!-- <slot node={subNode}> -->
<span>{subNode.text}</span>
<!-- </slot> -->
</svelte:self>
{/if}
</li>
{/each}
</ul>
This (with the commented lines still commented), produces the following type for the component, as per VS Code's tooltip:
function render<TItem extends NodeItem<TItem>>(): {
props: {
nodes: TItem[];
};
slots: {
default: {
node: TItem;
};
};
events: {};
}
Note how the node
variable is correctly inferred to be of type TItem
.
Now, if we uncomment the commented lines so the slotted content is passed down the recursion, the type changes to any:
function render<TItem extends NodeItem<TItem>>(): {
props: {
nodes: TItem[];
};
slots: {
default: {
node: any;
};
};
events: {};
}
This version still works properly, and I even get the desired result: The slot content specified by the consumer of the component is correctly used down in the recursion.
If I modify the component to provide separate slots (one for the root element and one for the recursion part), then the node
variable regains its correct type of TItem
, and the new slot's node
variable is of type any
. So I guess this hints to the fact that the problem is only inside <svelte:self>
, as the OP of this issue originally stated.
My desired result would be to not lose the correct data type when <svelte:self>
is used.
I'll continue my research, as my ultimate goal is to create specialized variations of this base component, and I suspect it might reveal more problems.
Thank you, team, for your efforts making this amazing framework possible.
Describe the bug
Normally, when I pass a typed prop to a slot, components passing in an element to that slot can access a typed copy of that prop from the parent.
Example:
But I noticed one case where the slot props do not get types as expected. I was creating a component to represent tree structures that allows for custom rendering of each node using slots (see my reproduction repo for the slimmed-down code). It uses
<svelte:self>
to render deeper levels of the tree recursively (very similar to the tutorial onsvelte:self
, but allowing for custom rendering of the node). In that case, any slots placed inside the<svelte:self>
do not retain the types of the props, and end up asany
.Reproduction
Here's a repo from a Skeleton project sveltekit build with the issue demonstrated:
https://github.com/fritz-c/svelte-nested-slot-type-issue
Here is the commit with the changes I made isolated:
https://github.com/fritz-c/svelte-nested-slot-type-issue/commit/906dde5f57cd066aeb3db90bcc075eef4d1bc6cf
Logs
No response
System Info
Severity
annoyance