Lesson 7 / 25
$props
Typed inputs with defaults.
Destructuring props
A component reads its inputs with let { title, count = 0, ...rest } = $props(). Defaults apply when the parent passes undefined; the rest pattern collects remaining attributes, which you can spread onto an element with {...rest}. Props update when the parent changes them. With TypeScript, describe them with an interface and annotate the destructuring: let { title }: Props = $props(). You can extend element attribute types such as HTMLButtonAttributes from svelte/elements. Treat props as read-only unless they are bindable. Svelte 4 used export let title; and $$restProps.
Data down, callbacks and snippets in
Components receive props, report changes through callbacks or bindings, and accept markup as snippets.
A typed Button component
Defaults, rest props and spread.
<!-- Button.svelte -->
<script lang="ts">
import type { HTMLButtonAttributes } from 'svelte/elements';
interface Props extends HTMLButtonAttributes {
variant?: 'primary' | 'ghost';
label: string;
}
let { variant = 'primary', label, ...rest }: Props = $props();
</script>
<button class={variant} {...rest}>{label}</button>
<!-- Usage in a parent:
<Button label="Save" type="submit" />
<Button label="Cancel" variant="ghost" onclick={close} />
-->Use $props.id for accessible ids
Svelte 5 provides $props.id() to generate an id unique to the component instance and stable between server and client, useful for label and aria attributes. Check the docs for your version.
Quick check: How does a Svelte 5 component declare a prop with a default value?
- let { size = 16 } = $props();
- export let size = 16;
- const size = $state.prop(16);
- props.size ||= 16;
Answer
let { size = 16 } = $props(); — Svelte 4 used export let; Svelte 5 uses $props.