How to extend the H3Event context type in Nuxt 3
Asked Answered
G

2

6

In the Nuxt 3 documentation, there's an example that shows using server middleware to annotate requests with additional information via event.context:

export default defineEventHandler((event) => {
  event.context.auth = { user: 123 }
})

However, there is no example of how to make the corresponding TypeScript typing for this. I'd prefer my event.context.auth not to be an any type.

The standard TypeScript library type extension method doesn't seem to work correctly here. I tried to make a shims.d.ts containing the following:

declare module 'h3' {
  interface H3EventContext {
    auth: AuthSession
  }
}

However, this breaks the type inference on the defineEventHandler function, making all event parameters into implicit anys. How can I declare my event context type without breaking stuff?

Geoffrey answered 26/5, 2023 at 14:9 Comment(0)
S
9

For that we can use TypeScript's Declaration Merging. As Nuxt uses h3 module behind the scenes, so we need to extend the h3 module and add our custom types. We can do something like this:

type MyFancyAuthType = {
  user: number
}

declare module 'h3' {
  interface H3EventContext {
    auth: MyFancyAuthType;
    // any other type
  }
}

export default defineEventHandler((event) => {
  // Here you will be able to access .auth on context with proper intellisense
  event.context.auth = { user: 123 }
})

You may explicitly define this in a separate file for example shim.d.ts. If you do so you need to tell TypeScript compiler.

tsconfig.json

{
  ...
  "files": ["shim.d.ts"]
  ...
}

Further, you need to make sure you must add export default {}. It should be like this:

shim.d.ts

...
declare module 'h3' {
  ...
}

// this is important
export default {};

Please note that while this is a widely adopted convention in the TypeScript community, it is not an official language feature documented by TypeScript itself.

Sloppy answered 27/5, 2023 at 22:3 Comment(1)
I tried this earlier, but sadly when placed in a separate declaration file, it causes all defineEventHandler functions to somehow lose their type inference entirely such that the event parameter becomes an any. Not sure what's happening there!Geoffrey
M
1

I'm not sure why your event becomes typed as any. It shouldn't do that and to test this I created an example on StackBlitz that demonstrates that what you did should work as intended.

https://stackblitz.com/edit/nuxt-starter-uhgayq?file=server%2Fapi%2Ftest.ts

The event is of type H3Event, event.context is H3EventContext and event.context.authenticatedUser is User. The User is defined in /server/user.ts

Maybe I'm missing something, but as you can see it should work fine the way you did it.

Manriquez answered 11/8, 2023 at 15:13 Comment(1)
Doesn't seem to be giving correct types in your example.Gleeful

© 2022 - 2024 — McMap. All rights reserved.