Description
Describe the problem
Svelte 5's reactivity introduces a requirement for at least one layer deep of nesting when reactive state is defined outside of the top level of a component, and in many cases, will likely have even deeper nested reactive properties. The necessity for nested property access adds a level of verbosity which can make the code less readable and harder to manage.
e.g.
import {dimensions} from './dimensions';
function resetDimensions() {
dimensions.value.width = 1920;
dimensions.value.height = 1080;
}
dimensions.value.area = 0; // this will error, as area property does not have a setter
const aspectRatio = $derived(dimensions.value.width / dimensions.value.height);
$effect(() => {
console.log(`Aspect Ratio changed to ${aspectRatio}`);
})
Describe the proposed solution
Introduce a new rune, $alias()
, which enables the creation of new variables from reactive properties and the destructuring of nested reactive properties while retaining reactivity/object property reference. The $alias()
rune essentially instructs the compiler to replace variable references with the expanded property access wherever the aliased or destructured variable is referenced, ensuring the reactivity of the original properties is maintained.
The Svelte compiler ideally should issue a warning on attempts to assign to referenced properties that don't have setters, as this is a limitation of assigning primitive values in javascript.
e.g. the example above could instead be writted as:
import {dimensions} from './dimensions';
let { value: { width, height, area } } = $alias(dimensions);
function resetDimensions() {
width = 1920;
height = 1080;
}
area = 0; // Svelte should issue a compiler warning as `dimensions.value.area` does not have a setter. JS can't catch this unfortunately.
const aspectRatio = $derived(width / height);
$effect(() => {
console.log(`Aspect Ratio changed to ${aspectRatio}`);
})
If desired, you should also be able to create variables using variable assignment instead of destructuring as well. i.e.
let width = $alias(dimensions.value.width);
let height = $alias(dimensions.value.height);
let area = $alias(dimensions.value.area);
Alternatives considered
Some alternative naming has been suggested such as $bind()
, $link()
, $expose()
, or $bridge()
.
Otherwise the alternative is we continue to require always directly accessing nested properties.
Importance
nice to have