tracking for shynet analytics when Javascript is disabled End-to-end type safety with Svelte 5 and SvelteKit 2 — Hugo Sum

End-to-end type safety with Svelte 5 and SvelteKit 2

Back in Svelte 4 and SvelteKit 1, you can use PageData and LayoutData to annotate the type of data passed from a load function in +page.svelte and +layout.svelte respectively to achieve end-to-end type safety. These two types are generated by SvelteKit based on the value returned by the load function.

For example, assuming we fetch data from an API in a load function as the following.

+page.server.ts
import type { PageServerLoad } from './$types';

export const load: PageServerLoad = async ({ params, route, parent }) => {
    const { cat, dog } = await getAnimals() // cat has type Cat, dog has type Dog

    return {
        cat: cat,
        dog: dog
    };
};

You can then import PageData to annotate the data props in your component.

+page.svelte
<script context="module" lang="ts">
	import type { PageData } from './$types';
</script>

<script lang="ts">
	export let data: PageData; // the type here will be { cat: Cat, dog: Dog } 
</script>

Type safety with $props() rune in Svelte 5

In Svelte 5, with the introduction of $props() rune, every Svelte component only accepts a single object as its props. Since the type of $props() returns any by default, and does not accept type parameters, you have to add a type annotation to the variable to achieve type safety.

+page.svelte
<script context="module" lang="ts">
    import type { PageData } from './$types';
</script>

<script lang="ts">
    export let data: PageData;
    let { data }: { data: PageData } = $props();
</script>

Simplify type annotation with PageProps

With the release of SvelteKit 2.16.0, new types PageProps and LayoutProps are introduced to simplify the type annotation for props in +page.svelte and +layout.svelte respectively.

+page.svelte
<script context="module" lang="ts">
    import type { PageData } from './$types';
    import type { PageProps } from './$types';
</script>

<script lang="ts">
    let { data }: { data: PageData } = $props();
    let { data }: PageProps = $props();
</script>

Under the hood, PageProps and LayoutProps reuse PageData and LayoutData in their definition, nothing too special there.

export type PageProps = { data: PageData; form: ActionData };

Hugo Sum

A Hongkonger living in the UK. The only thing I know is there is so much I don't know.

Enjoy reading my blog?

Subscribe to a monthly newsletter and join my technical adventure.