Skip to content

Svelte 5: Type problem with async function in $effect runeΒ #9520

@njezersek

Description

@njezersek

Describe the problem

When using the $effect rune with async function, TypeScript raises an error:

Argument of type '() => Promise<void>' is not assignable to parameter of type '() => void | (() => void)'.
  Type 'Promise<void>' is not assignable to type 'void | (() => void)'.

However Svelte seems to work just fine with async function in `$effect$.

Here is a small example to demonstrate the problem:

<script lang="ts">
	let key = $state("test");
	$effect(async () => {
		let res = await fetch(`http://localhost:8080/api/${key}`);
		let json = await res.json();
		console.log(key, json);
	})
</script>

<input type="text" bind:value={key}>

Describe the proposed solution

Update the type definition to include async functions.

From:

declare function $effect(fn: () => void | (() => void)): void;

to:

declare function $effect(fn: () => void | (() => void) | Promise<void>): void;

Note: I realize that using an async function with $effect might make returning callback hard to handle. Thats why I propose updating the type declaration to only alow void async functions.

Alternatives considered

A possible workaround is to introduce another function:

<script lang="ts">
	let key = $state("test");
	$effect(() => {
		(async () => {
			let res = await fetch(`http://localhost:8080/api/${key}`);
			let json = await res.json();
			console.log(key, json);
		})()
	})
</script>

<input type="text" bind:value={key}>

Importance

would make my life easier

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions