Skip to content

Singular $prop rune for simple properties #16494

@EggAllocationService

Description

@EggAllocationService

Describe the problem

Svelte 5 runes are overall a much needed upgrade, but I think one area where they are a step back is the experience declaring props, especially when using TypeScript.

For example, this (Svelte 4 style):

export let initialValue: number | undefined;
export let onUpdate = (a: number) => {};
export let color = "test";
export let extra = false;

Is a much nicer developer experience than this, which is what we have now with runes:

interface Props {
  initialValue: number | undefined,
  onUpdate: (a: number) => void,
  color: string,
  extra: boolean
}

let {
  initialValue,
  onUpdate = (a) => {},
  color = "test",
  extra = false
}: Props = $props();

The repetition of property names and having to define a separate type make Svelte 5 a much more grating experience for those who depend on TypeScript.

This alone is really putting me off migrating to Svelte 5, which sucks because the new runes are such a massive improvement over stores.

Describe the proposed solution

I don't think bringing back export let is a good idea as it's not very explicit and doesn't fit in now that we have runes.

I propose adding a singular version of the $props() rune, which can be used on the right hand side of a let assignment at the top level of a component's script. It would use the variable name on the left hand side as the property name, and can be given a default value.

The above code now turns into this:

let initialValue: number | undefined = $prop();
let onUpdate = $prop((a:number) => {});
let color = $prop("test")
let extra = $prop(false)

This eliminates the duplication of property names and eliminates the need for messy destructuring, especially in typescript where you'd need to declare a separate type or inline with the destructuring which hurts readability and maintainability.

The $bindable() rune could also be expanded to have the same behaviour, where

let value: string = $bindable("Default Text")

would declare a bindable string property value.

Importantly, we keep the $props() rune for more complex use cases, but for simple components with a few properties I think this is much nicer from a DX perspective.

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