TypeScript
mongoose-guard is written in TypeScript and ships its own types. You don’t install anything extra. In Express, req.validated is typed as Record<string, unknown> | undefined automatically. For a precise type, pass a type argument to createGuard or the web guard, usually built from your schema with Mongoose’s InferSchemaType and Pick.
What’s typed out of the box
Section titled “What’s typed out of the box”import type { Guard, // what createGuard returns GuardableModel, // what counts as a model GuardOptions, // { allow, partial?, unknown? } GuardResult, // { ok: true, data } | { ok: false, issues } Issue, // { code, path, message, rule? } IssueCode, // "invalid_body" | "unsafe_key" | ... UnknownFieldPolicy, // "reject" | "strip"} from "mongoose-guard";
import type { ExpressGuardOptions, InvalidHandler } from "mongoose-guard/express";import type { RequestGuard } from "mongoose-guard/web";GuardResult is a discriminated union, so checking ok narrows it:
const result = await userGuard.validate(body);if (result.ok) { result.data; // available} else { result.issues; // available}req.validated in Express
Section titled “req.validated in Express”Importing mongoose-guard/express anywhere in your project adds validated to Express’s Request type:
app.post("/users", guard(User, { allow: ["name"] }), (req, res) => { req.validated; // Record<string, unknown> | undefined});It’s undefined on routes without a guard, which is why the type includes it.
A precise type for the data
Section titled “A precise type for the data”mongoose-guard can’t work out the type from your allow list on its own, because the list is just an array of strings. You say what you expect, and the type argument is applied to data:
import { type InferSchemaType } from "mongoose";import { createGuard } from "mongoose-guard";
type UserFields = InferSchemaType<typeof userSchema>;type SignupBody = Pick<UserFields, "name" | "email" | "password">;
const signupGuard = createGuard<SignupBody>(User, { allow: ["name", "email", "password"] });
const result = await signupGuard.validate(body);if (result.ok) { result.data.email; // string}The web adapter takes the same type argument:
const validateSignup = guard<SignupBody>(User, { allow: ["name", "email", "password"] });For Express, read req.validated through a small helper:
function validated<T>(req: Request): T { return req.validated as T;}
const body = validated<SignupBody>(req);Module resolution
Section titled “Module resolution”The package works with every moduleResolution setting:
moduleResolution | Works |
|---|---|
bundler | yes |
node16 / nodenext (ESM or CommonJS) | yes |
node / node10 (common in older CommonJS projects) | yes |
That’s checked on every release with @arethetypeswrong/cli.
Your models, any style
Section titled “Your models, any style”mongoose-guard accepts anything that has a Mongoose schema and can be constructed like a model. Models declared with generics (model<IUser>("User", schema)), InferSchemaType, or no types at all all work.