Clifton Labrum
Clifton Labrum

Reputation: 14158

How Do I Add TypeScript to a SvelteKit Handle Function in Hooks?

I am currently using the following in my hooks.ts file in a SvelteKit app:

export async function handle({ event, resolve }) {
  console.log(event.locals) //<-- Works fine
}

I'm trying to figure out how to use types on the event and resolve parameters. As far as I can tell, event works like this:

import type { RequestEvent } from '@sveltejs/kit'

export async function handle(event: RequestEvent, resolve: ???){
  ...
}

But I can't figure out how to type the resolve parameter. The docs here show this:

interface Handle {
  (input: {
    event: RequestEvent;
    resolve(
      event: RequestEvent,
      opts?: ResolveOptions
    ): MaybePromise<Response>;
  }): MaybePromise<Response>;
}

From my limited TypeScript knowledge, it looks like resolve is a function with two parameters that returns a promise. But how do I write that out in the handle function declaration?

Upvotes: 6

Views: 3879

Answers (3)

Casey Plummer
Casey Plummer

Reputation: 3088

If you add 'satisfies Handle' to your function you'll get the 'any' warnings to go away.

import type { Handle } from '@sveltejs/kit';

export const handle = (async ({ event, resolve }) => {
  if (event.url.pathname.startsWith('/custom')) {
    return new Response('custom response');
  }

  const response = await resolve(event);
  return response;
}) satisfies Handle;

Reference: https://kit.svelte.dev/docs/hooks#server-hooks

For that above link, be sure to turn on TypeScript to see the correct examples:

enter image description here

Upvotes: 1

brunnerh
brunnerh

Reputation: 185225

As an alternative to typing the function as a whole, which is convenient in that it types arguments and return type, you can type those separately and retain the export async function syntax.

The argument type does not have a name, though, so you need to extract it manually from Handle. Note that there actually is only one argument, which is being destructured. E.g.

// Maybe export this from elsewhere to not repeat it
type HandleParams = Parameters<Handle>[0];

export async function handle({ event, resolve }: HandleParams) : Promise<Response> {
    // ...
}

The original return type uses MaybePromise<T> to allow synchronous and async returns. You can just only use Promise if the function is actually async.

There also is another helper type like Parameters that would allow you to extract the return type generically from Handle:

type HandleResult = ReturnType<Handle>;

Upvotes: 2

Ruan Mendes
Ruan Mendes

Reputation: 92314

I think your question is (or should be 😁): "How do I tell TypeScript that my function is of type Handle?".

I think the simplest way would be to create a variable out of the function so you can easily type it.

export const handle: Handle = async function ({ event, resolve }) {
  console.log(event.locals);
}

Notice that you don't need to type event or resolve separately, TS already knows about your function's argument and return type. It will flag your existing implementation because it's not returning a MaybePromise<Response>

Upvotes: 11

Related Questions