Reputation: 3654
I am using passport in a TypeScript project. The DefinitelyTyped type definition for passport overrides the Express request to include the user
property. But it defines the user as being an empty interface:
index.d.ts
declare global {
namespace Express {
...
// tslint:disable-next-line:no-empty-interface
interface User {}
interface Request {
...
user?: User;
...
}
}
}
However throughout my application I want req.user
to be this type interface:
interface User {
id: number
username: string,
profilePicture: string,
name: string
}
I am tired of writing req.user as User | null
throughout my application. I could override the interface definition in the definition file directly but this seems bad practise modifying a file in node_modules
that will likely get overwritten if I update the type module.
Is there a way to write a definition file in my src folder that overrides Express.User
? I have tried myself copying and amending the definition file to my src directory but it says
Augmentations for the global scope can only be directly nested in external modules or ambient module declarations
Without declare global
tsc still treats req.user
as being of an empty interface.
What configuration do I have to include in tsconfig.json
to then pickup this override?
Upvotes: 6
Views: 5657
Reputation: 31823
Interface declarations in the same scope are merged. That is to say, the following
interface A {
name: string;
}
interface A {
id: number;
}
declares a single interface, namely A
, with two properties, name
and id
.
Therefore, simply use the same technique used by passport to adjust the types.
My convention is to create an augmentations file in the root of my project when I want to augment the type declarations of any dependencies such as express.
augmentations.d.ts
// ensure file is parsed as a module
export {}
// access the global scope inside our module
declare global {
namespace Express {
// introduce another declaration of interface Express.User which will merge with any others
interface User {
id: number,
username: string,
profilePicture: string,
name: string
}
}
}
Upvotes: 11