How to add custom types to Nuxt3 server API context
Nuxt3 is a Hybrid (Full-Stack) Vue 3 framework. It allows you to create file-based API routes on the server-side which uses Nitro and H3 under the hood. Here's a trick to help with TypeScript types on your server context.
Getting started with Nuxt 3
First we actually need an example, to start a Nuxt 3 project simply do:
npx nuxi init my-awesome-project
This will generate a new nuxt app for you, once it's cloned, run:
cd my-awesome-project && yarn install && npx nuxi prepare
This will install all your dependencies and npx nuxi prepare
will generate the base types of your project.
Creating an API route
server/api/todos.get.ts
export default defineEventHandler(async (event) => ['todo1', 'todo2'])
Create the file above, you don't need to import anything because defineEventHandler
is part of Nuxt3's Auto Imports. The event
has a property called context
and it's native type is Record<string, any>
. So let's add a fake 'Auth' module in a global middleware. First, let us protect our route:
export default defineEventHandler(async (event) => {
const user = event.context.auth; // 'auth' will not be typed, we want to see what's available on auth.
if (user.validate(/* Does this accept params?? */)) {
return ['todo1', 'todo2'];
}
return []; // Not authed buddyyy.
})
The code above requires us to create a middleware to update the event context a little:
server/middleware/auth.ts
export interface User {
id: string;
email: string;
validate: (forceRefresh?: boolean ) => boolean; // oh, it has a param 🤔
}
export default defineEventHandler((event) => {
const user: User = {
id: '1234',
email: '[email protected]',
validate(forceRefresh) {
// Some logic here using forceRefresh etc.
return true;
},
};
event.context.auth = user;
});
Above we do clearly define the type of User, but in server/api/todos.get.ts
the type will be 'any' on the context, leaving us blind. So here's how we can work around that:
server/context.d.ts
import type {User} from './middleware/auth';
import type {IncomingMessage, H3Event} from 'h3';
declare module 'h3' {
interface CompatibilityEvent extends IncomingMessage, H3Event {
context: {
[key: string]: any; // or 'unknown' 🤔?
auth?: User;
};
}
}
Now we have full typing of our context on the Nuxt 3 API routes. As you add stuff to context
just keep updating the types in this file:
Thank you for reading and I hope this helped you out. If you want to Support Me feel free 😀, other ways for you to follow me is on Twitter or on Youtube. Happy hacking!