Skip to content

Change rune parameter types from void functions to unknown functions #15827

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
WillsterJohnson opened this issue Apr 23, 2025 · 1 comment
Open

Comments

@WillsterJohnson
Copy link

WillsterJohnson commented Apr 23, 2025

Describe the problem

An abstract example;

Sometimes an effect is a single expression

$effect(() => {
  goDoStuffWith(myState);
})

Me, and probably a good few others, like to shorten single-statement callbacks into one line

() => doDoStuffWith(myState)

However, this callback cant always be passed to $effect because of an incompatible return type

declare function $effect(fn: () => void | (() => void)): void
//                                 ^ if the single expression resolves to a value,
//                                   it violates the `void` type

A more tangible example;

I have three boolean states, call them A, X, and Y.

When X changes, set A = X, when Y changes, set A = Y.

I can't do this with a derived, as I can't know which of X or Y changed

let A = $derived.by(() => {
  return X
  return Y // you can't even express the above idea
})

I can do it with effects though;

$effect(() => {
  A = X
})
$effect(() => {
  A = Y
})

I would prefer to write it as follows to save a bit on vertical space, as I don't find the readability to be impaired by collapsing the function body (tbh, I find the following more readable);

$effect(() => A = X)
$effect(() => A = Y)

But assignment expressions resolve to the assigned value, and in this case thats always a boolean, not assignable to void.

Describe the proposed solution

Use unknown instead;

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

The same for other effects; $effect.root, $effect.pre


Workarounds;

just use javascript void. I find this reduces readability, as it adds more boilerplate and forces brackets to stack up at the end.

$effect(() => void (A = X))
$effect(() => void (A = Y))

or...

Adding this to app.d.ts (or other global declaration) applies the proposed change as a patch

declare global {
  function $effect(fn: () => unknown | (() => unknown)): void
}

Importance

nice to have

@paoloricciuti
Copy link
Member

The return value of an effect can be void but if you return something it needs to be the cleanup function. I think this change will be confusing because then nothing stops you from doing

$effect(()=>{
    return 3;
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants