Daaang Amy
open main menu

Svelte: Components with Typed Props

/ 2 min read
Last updated:

How to set up typed props for svelte components.

Use Button.svelte.d.ts.

Given a Button svelte component:

// Button.svelte

 <script lang="ts">
     export let disabled: boolean = false;
     export let kind: "primary"
         | "danger"
         | "secondary"
         | "ghost"
         | "outline"  = "primary";
     export let size: "sm" | "md" | "lg" = "md";
     export let type: string = "button";
 </script>

<button
   class:btn={true}
   class:btn-disabled={disabled}
   class:btn-primary={kind === "primary"}
   class:btn-secondary={kind === "secondary"}
   class:btn-danger={kind === "danger"}
   class:btn-ghost={kind === "ghost"}
   class:btn-outline={kind === "outline"}
   class:btn-sm={size === "sm"}
   class:btn-md={size === "md"}
   class:btn-lg={size === "lg"}
   type={type}
   tabindex="0"
   disabled={disabled}
   on:click
   {...$$restProps}
>
   <slot></slot>
 </button>

In a file called Button.svelte.d.ts we can define our custom button props.

// Button.svelte.d.ts

import { SvelteComponentTyped } from "svelte";

export interface ButtonProps
extends svelte.JSX.HTMLAttributes<HTMLElementTagNameMap["button"]> {
   disabled: boolean;
   kind: "primary" | "danger" | "secondary" | "ghost" | "outline";
   size: "sm" | "md" | "lg";
   type: string = "button";
};

export default class Button extends SvelteComponentTyped<ButtonProps> {};

How to type custom events with your custom components

Add a custom event to your component using createEventDispatcher and we will also need to decleare a new type for the data that will be passed once the event is triggered.

In this example we’re adding a custom-click event and ButtonData type.

// Button.svelte

 <script lang="ts">
     // ....code

     import { createEventDispatcher } from 'svelte';
     import { ButtonData } from './Button.svelte.d.ts';
     const dispatch = createEventDispatcher();

     // data type 
     const btnData: ButtonData = {
         name: 'hello'
     };
 </script>

<button
   // ....code
   {...$$restProps}
   on:click
   on:click={() => {
      // make sure to dispatch the regular on:click event
      dispatch("click");
      // dispatch your custom click event
      dispatch("custom-click", btnData);
   }}
>
  <slot></slot>
 </button>

Define the new custom event type in Button.svelte.d.ts.

// Button.svelte.d.ts

import { SvelteComponentTyped } from "svelte";

export interface ButtonData {
   name: string;
}

// ...ButtonProps code here...

export default class Button extends SvelteComponentTyped<
   ButtonProps,
   {
      // click:custom-click: your custom event
      // ButtonData: the type of the data sent
   }
> {};

Usage

// Main.svelte

 <script lang="ts">
     import Button from "./Button.svelte";
 </script>

<Button
   on:click:custom-click={(e: CustomEvent<ButtonData>) => {
      console.log(e.detail); // data from event dispatched
   }}
> Click me!</Button>