Skip to main content
Version: 10.x

Middlewares

You are able to add middleware(s) to a procedure with the t.procedure.use() method. The middleware(s) will wrap the invocation of the procedure and must pass through its return value.

Authorization

In the example below, any call to a protectedProcedure will ensure that the user is an "admin" before executing.

ts
import { TRPCError, initTRPC } from '@trpc/server';
 
interface Context {
user?: {
id: string;
isAdmin: boolean;
// [..]
};
}
 
const t = initTRPC.context<Context>().create();
export const middleware = t.middleware;
export const publicProcedure = t.procedure;
export const router = t.router;
 
const isAdmin = middleware(async ({ ctx, next }) => {
if (!ctx.user?.isAdmin) {
throw new TRPCError({ code: 'UNAUTHORIZED' });
}
return next({
ctx: {
user: ctx.user,
},
});
});
 
export const adminProcedure = publicProcedure.use(isAdmin);
ts
import { TRPCError, initTRPC } from '@trpc/server';
 
interface Context {
user?: {
id: string;
isAdmin: boolean;
// [..]
};
}
 
const t = initTRPC.context<Context>().create();
export const middleware = t.middleware;
export const publicProcedure = t.procedure;
export const router = t.router;
 
const isAdmin = middleware(async ({ ctx, next }) => {
if (!ctx.user?.isAdmin) {
throw new TRPCError({ code: 'UNAUTHORIZED' });
}
return next({
ctx: {
user: ctx.user,
},
});
});
 
export const adminProcedure = publicProcedure.use(isAdmin);
ts
import { adminProcedure, publicProcedure, router } from './trpc';
 
const adminRouter = router({
secretPlace: adminProcedure.query(() => 'a key'),
});
 
export const appRouter = router({
foo: publicProcedure.query(() => 'bar'),
admin: adminRouter,
});
ts
import { adminProcedure, publicProcedure, router } from './trpc';
 
const adminRouter = router({
secretPlace: adminProcedure.query(() => 'a key'),
});
 
export const appRouter = router({
foo: publicProcedure.query(() => 'bar'),
admin: adminRouter,
});
tip

See Error Handling to learn more about the TRPCError thrown in the above example.

Logging

In the example below timings for queries are logged automatically.

ts
const loggerMiddleware = middleware(async ({ path, type, next }) => {
const start = Date.now();
const result = await next();
const durationMs = Date.now() - start;
result.ok
? logMock('OK request timing:', { path, type, durationMs })
: logMock('Non-OK request timing', { path, type, durationMs });
 
return result;
});
 
export const loggedProcedure = publicProcedure.use(loggerMiddleware);
ts
const loggerMiddleware = middleware(async ({ path, type, next }) => {
const start = Date.now();
const result = await next();
const durationMs = Date.now() - start;
result.ok
? logMock('OK request timing:', { path, type, durationMs })
: logMock('Non-OK request timing', { path, type, durationMs });
 
return result;
});
 
export const loggedProcedure = publicProcedure.use(loggerMiddleware);
ts
import { loggedProcedure, router } from './trpc';
 
export const appRouter = router({
foo: loggedProcedure.query(() => 'bar'),
abc: loggedProcedure.query(() => 'def'),
});
ts
import { loggedProcedure, router } from './trpc';
 
export const appRouter = router({
foo: loggedProcedure.query(() => 'bar'),
abc: loggedProcedure.query(() => 'def'),
});

Context Swapping

Context swapping in tRPC is a very powerful feature that allows you to create base procedures that dynamically infers new context in a flexible and typesafe manner.

Below we have an example of a middleware that changes properties of the context, and procedures will receive the new context value:

ts
type Context = {
// user is nullable
user?: {
id: string;
};
};
 
const isAuthed = middleware(({ ctx, next }) => {
// `ctx.user` is nullable
if (!ctx.user) {
(property) user?: { id: string; } | undefined
throw new TRPCError({ code: 'UNAUTHORIZED' });
}
 
return next({
ctx: {
// ✅ user value is known to be non-null now
user: ctx.user,
(property) user: { id: string; }
},
});
});
 
const protectedProcedure = publicProcedure.use(isAuthed);
protectedProcedure.query(({ ctx }) => ctx.user);
(property) user: { id: string; }
ts
type Context = {
// user is nullable
user?: {
id: string;
};
};
 
const isAuthed = middleware(({ ctx, next }) => {
// `ctx.user` is nullable
if (!ctx.user) {
(property) user?: { id: string; } | undefined
throw new TRPCError({ code: 'UNAUTHORIZED' });
}
 
return next({
ctx: {
// ✅ user value is known to be non-null now
user: ctx.user,
(property) user: { id: string; }
},
});
});
 
const protectedProcedure = publicProcedure.use(isAuthed);
protectedProcedure.query(({ ctx }) => ctx.user);
(property) user: { id: string; }

Extending middlewares

info

We have prefixed this as unstable_ as it's a new API, but you're safe to use it! Read more.

We have a powerful feature called .pipe() which allows you to extend middlewares in a typesafe manner.

Below we have an example of a middleware that extends a base middleware(foo). Like the context swapping example above, piping middlewares will change properties of the context, and procedures will receive the new context value.

ts
const fooMiddleware = middleware(({ next }) => {
return next({
ctx: {
foo: 'foo' as const,
},
});
});
 
const barMiddleware = fooMiddleware.unstable_pipe(({ ctx, next }) => {
ctx.foo;
(property) foo: "foo"
return next({
ctx: {
bar: 'bar' as const,
},
});
});
 
const barProcedure = publicProcedure.use(barMiddleware);
barProcedure.query(({ ctx }) => ctx.bar);
(parameter) ctx: { foo: "foo"; bar: "bar"; }
ts
const fooMiddleware = middleware(({ next }) => {
return next({
ctx: {
foo: 'foo' as const,
},
});
});
 
const barMiddleware = fooMiddleware.unstable_pipe(({ ctx, next }) => {
ctx.foo;
(property) foo: "foo"
return next({
ctx: {
bar: 'bar' as const,
},
});
});
 
const barProcedure = publicProcedure.use(barMiddleware);
barProcedure.query(({ ctx }) => ctx.bar);
(parameter) ctx: { foo: "foo"; bar: "bar"; }

Beware that the order in which you pipe your middlewares matter and that the context must overlap. An example of a forbidden pipe is shown below. Here, the fooMiddleware overrides the ctx.a while barMiddleware still expects the root context from the initialization in initTRPC - so piping fooMiddleware with barMiddleware would not work, while piping barMiddleware with fooMiddleware does work.

ts
import { initTRPC } from '@trpc/server';
 
const t = initTRPC
.context<{
a: {
b: 'a';
};
}>()
.create();
 
const fooMiddleware = t.middleware(({ ctx, next }) => {
ctx.a; // 👈 fooMiddleware expects `ctx.a` to be an object
(property) a: { b: 'a'; }
return next({
ctx: {
a: 'a' as const, // 👈 `ctx.a` is no longer an object
},
});
});
 
const barMiddleware = t.middleware(({ ctx, next }) => {
ctx.a; // 👈 barMiddleware expects `ctx.a` to be an object
(property) a: { b: 'a'; }
return next({
ctx: {
foo: 'foo' as const,
},
});
});
 
// ❌ `ctx.a` does not overlap from `fooMiddleware` to `barMiddleware`
fooMiddleware.unstable_pipe(barMiddleware);
Argument of type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _meta: object; }, { ...; }>' is not assignable to parameter of type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _output_out: unknown; }, { ...; }> | MiddlewareFunction<...>'. Type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _meta: object; }, { ...; }>' is not assignable to type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _output_out: unknown; }, { ...; }>'. Types of property 'unstable_pipe' are incompatible. Type '<$Params extends import("/vercel/path0/www/node_modules/@trpc/server/dist/core/procedure").ProcedureParams<import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").AnyRootConfig, unknown, unknown, unknown, unknown, unknown, unknown>>(fn: import("/vercel/path0/www/node_modules/@trpc/server/dis...' is not assignable to type '<$Params extends import("/vercel/path0/www/node_modules/@trpc/server/dist/core/procedure").ProcedureParams<import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").AnyRootConfig, unknown, unknown, unknown, unknown, unknown, unknown>>(fn: import("/vercel/path0/www/node_modules/@trpc/server/dis...'. Two different types with this name exist, but they are unrelated. Types of parameters 'fn' and 'fn' are incompatible. Type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareBuilder<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/form...' is not assignable to type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareBuilder<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/form...'. Two different types with this name exist, but they are unrelated. Type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _output_out: unknown; }, any>' is not assignable to type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _output_out: unknown; }, any> | MiddlewareFunction<...>'. Type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareBuilder<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/form...' is not assignable to type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareBuilder<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/form...'. Two different types with this name exist, but they are unrelated. Types of property '_middlewares' are incompatible. Type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareFunction<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/for...' is not assignable to type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareFunction<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/for...'. Two different types with this name exist, but they are unrelated. Type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareFunction<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/for...' is not assignable to type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareFunction<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/for...'. Two different types with this name exist, but they are unrelated. Type '{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/formatter").DefaultErrorShape; transformer: import("/vercel/path0/www/node_modules/@trpc/server/d...' is not assignable to type '{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/formatter").DefaultErrorShape; transformer: import("/vercel/path0/www/node_modules/@trpc/server/d...'. Two different types with this name exist, but they are unrelated. Types of property '_ctx_out' are incompatible. Type 'Overwrite<{ a: { b: "a"; }; }, { foo: "foo"; }>' is not assignable to type 'Overwrite<Overwrite<{ a: { b: "a"; }; }, { a: "a"; }>, { foo: "foo"; }>'. Type 'Overwrite<{ a: { b: "a"; }; }, { foo: "foo"; }>' is not assignable to type 'Omit<Overwrite<{ a: { b: "a"; }; }, { a: "a"; }>, "foo">'. Types of property 'a' are incompatible. Type '{ b: "a"; }' is not assignable to type '"a"'.2345Argument of type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _meta: object; }, { ...; }>' is not assignable to parameter of type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _output_out: unknown; }, { ...; }> | MiddlewareFunction<...>'. Type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _meta: object; }, { ...; }>' is not assignable to type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _output_out: unknown; }, { ...; }>'. Types of property 'unstable_pipe' are incompatible. Type '<$Params extends import("/vercel/path0/www/node_modules/@trpc/server/dist/core/procedure").ProcedureParams<import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").AnyRootConfig, unknown, unknown, unknown, unknown, unknown, unknown>>(fn: import("/vercel/path0/www/node_modules/@trpc/server/dis...' is not assignable to type '<$Params extends import("/vercel/path0/www/node_modules/@trpc/server/dist/core/procedure").ProcedureParams<import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").AnyRootConfig, unknown, unknown, unknown, unknown, unknown, unknown>>(fn: import("/vercel/path0/www/node_modules/@trpc/server/dis...'. Two different types with this name exist, but they are unrelated. Types of parameters 'fn' and 'fn' are incompatible. Type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareBuilder<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/form...' is not assignable to type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareBuilder<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/form...'. Two different types with this name exist, but they are unrelated. Type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _output_out: unknown; }, any>' is not assignable to type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _output_out: unknown; }, any> | MiddlewareFunction<...>'. Type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareBuilder<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/form...' is not assignable to type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareBuilder<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/form...'. Two different types with this name exist, but they are unrelated. Types of property '_middlewares' are incompatible. Type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareFunction<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/for...' is not assignable to type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareFunction<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/for...'. Two different types with this name exist, but they are unrelated. Type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareFunction<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/for...' is not assignable to type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareFunction<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/for...'. Two different types with this name exist, but they are unrelated. Type '{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/formatter").DefaultErrorShape; transformer: import("/vercel/path0/www/node_modules/@trpc/server/d...' is not assignable to type '{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/formatter").DefaultErrorShape; transformer: import("/vercel/path0/www/node_modules/@trpc/server/d...'. Two different types with this name exist, but they are unrelated. Types of property '_ctx_out' are incompatible. Type 'Overwrite<{ a: { b: "a"; }; }, { foo: "foo"; }>' is not assignable to type 'Overwrite<Overwrite<{ a: { b: "a"; }; }, { a: "a"; }>, { foo: "foo"; }>'. Type 'Overwrite<{ a: { b: "a"; }; }, { foo: "foo"; }>' is not assignable to type 'Omit<Overwrite<{ a: { b: "a"; }; }, { a: "a"; }>, "foo">'. Types of property 'a' are incompatible. Type '{ b: "a"; }' is not assignable to type '"a"'.
 
// ✅ `ctx.a` overlaps from `barMiddleware` and `fooMiddleware`
barMiddleware.unstable_pipe(fooMiddleware);
ts
import { initTRPC } from '@trpc/server';
 
const t = initTRPC
.context<{
a: {
b: 'a';
};
}>()
.create();
 
const fooMiddleware = t.middleware(({ ctx, next }) => {
ctx.a; // 👈 fooMiddleware expects `ctx.a` to be an object
(property) a: { b: 'a'; }
return next({
ctx: {
a: 'a' as const, // 👈 `ctx.a` is no longer an object
},
});
});
 
const barMiddleware = t.middleware(({ ctx, next }) => {
ctx.a; // 👈 barMiddleware expects `ctx.a` to be an object
(property) a: { b: 'a'; }
return next({
ctx: {
foo: 'foo' as const,
},
});
});
 
// ❌ `ctx.a` does not overlap from `fooMiddleware` to `barMiddleware`
fooMiddleware.unstable_pipe(barMiddleware);
Argument of type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _meta: object; }, { ...; }>' is not assignable to parameter of type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _output_out: unknown; }, { ...; }> | MiddlewareFunction<...>'. Type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _meta: object; }, { ...; }>' is not assignable to type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _output_out: unknown; }, { ...; }>'. Types of property 'unstable_pipe' are incompatible. Type '<$Params extends import("/vercel/path0/www/node_modules/@trpc/server/dist/core/procedure").ProcedureParams<import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").AnyRootConfig, unknown, unknown, unknown, unknown, unknown, unknown>>(fn: import("/vercel/path0/www/node_modules/@trpc/server/dis...' is not assignable to type '<$Params extends import("/vercel/path0/www/node_modules/@trpc/server/dist/core/procedure").ProcedureParams<import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").AnyRootConfig, unknown, unknown, unknown, unknown, unknown, unknown>>(fn: import("/vercel/path0/www/node_modules/@trpc/server/dis...'. Two different types with this name exist, but they are unrelated. Types of parameters 'fn' and 'fn' are incompatible. Type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareBuilder<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/form...' is not assignable to type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareBuilder<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/form...'. Two different types with this name exist, but they are unrelated. Type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _output_out: unknown; }, any>' is not assignable to type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _output_out: unknown; }, any> | MiddlewareFunction<...>'. Type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareBuilder<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/form...' is not assignable to type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareBuilder<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/form...'. Two different types with this name exist, but they are unrelated. Types of property '_middlewares' are incompatible. Type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareFunction<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/for...' is not assignable to type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareFunction<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/for...'. Two different types with this name exist, but they are unrelated. Type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareFunction<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/for...' is not assignable to type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareFunction<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/for...'. Two different types with this name exist, but they are unrelated. Type '{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/formatter").DefaultErrorShape; transformer: import("/vercel/path0/www/node_modules/@trpc/server/d...' is not assignable to type '{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/formatter").DefaultErrorShape; transformer: import("/vercel/path0/www/node_modules/@trpc/server/d...'. Two different types with this name exist, but they are unrelated. Types of property '_ctx_out' are incompatible. Type 'Overwrite<{ a: { b: "a"; }; }, { foo: "foo"; }>' is not assignable to type 'Overwrite<Overwrite<{ a: { b: "a"; }; }, { a: "a"; }>, { foo: "foo"; }>'. Type 'Overwrite<{ a: { b: "a"; }; }, { foo: "foo"; }>' is not assignable to type 'Omit<Overwrite<{ a: { b: "a"; }; }, { a: "a"; }>, "foo">'. Types of property 'a' are incompatible. Type '{ b: "a"; }' is not assignable to type '"a"'.2345Argument of type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _meta: object; }, { ...; }>' is not assignable to parameter of type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _output_out: unknown; }, { ...; }> | MiddlewareFunction<...>'. Type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _meta: object; }, { ...; }>' is not assignable to type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _output_out: unknown; }, { ...; }>'. Types of property 'unstable_pipe' are incompatible. Type '<$Params extends import("/vercel/path0/www/node_modules/@trpc/server/dist/core/procedure").ProcedureParams<import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").AnyRootConfig, unknown, unknown, unknown, unknown, unknown, unknown>>(fn: import("/vercel/path0/www/node_modules/@trpc/server/dis...' is not assignable to type '<$Params extends import("/vercel/path0/www/node_modules/@trpc/server/dist/core/procedure").ProcedureParams<import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").AnyRootConfig, unknown, unknown, unknown, unknown, unknown, unknown>>(fn: import("/vercel/path0/www/node_modules/@trpc/server/dis...'. Two different types with this name exist, but they are unrelated. Types of parameters 'fn' and 'fn' are incompatible. Type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareBuilder<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/form...' is not assignable to type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareBuilder<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/form...'. Two different types with this name exist, but they are unrelated. Type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _output_out: unknown; }, any>' is not assignable to type 'MiddlewareBuilder<{ _config: RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: DefaultErrorShape; transformer: DefaultDataTransformer; }>; ... 5 more ...; _output_out: unknown; }, any> | MiddlewareFunction<...>'. Type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareBuilder<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/form...' is not assignable to type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareBuilder<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/form...'. Two different types with this name exist, but they are unrelated. Types of property '_middlewares' are incompatible. Type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareFunction<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/for...' is not assignable to type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareFunction<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/for...'. Two different types with this name exist, but they are unrelated. Type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareFunction<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/for...' is not assignable to type 'import("/vercel/path0/www/node_modules/@trpc/server/dist/core/middleware").MiddlewareFunction<{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/for...'. Two different types with this name exist, but they are unrelated. Type '{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/formatter").DefaultErrorShape; transformer: import("/vercel/path0/www/node_modules/@trpc/server/d...' is not assignable to type '{ _config: import("/vercel/path0/www/node_modules/@trpc/server/dist/core/internals/config").RootConfig<{ ctx: { a: { b: "a"; }; }; meta: object; errorShape: import("/vercel/path0/www/node_modules/@trpc/server/dist/error/formatter").DefaultErrorShape; transformer: import("/vercel/path0/www/node_modules/@trpc/server/d...'. Two different types with this name exist, but they are unrelated. Types of property '_ctx_out' are incompatible. Type 'Overwrite<{ a: { b: "a"; }; }, { foo: "foo"; }>' is not assignable to type 'Overwrite<Overwrite<{ a: { b: "a"; }; }, { a: "a"; }>, { foo: "foo"; }>'. Type 'Overwrite<{ a: { b: "a"; }; }, { foo: "foo"; }>' is not assignable to type 'Omit<Overwrite<{ a: { b: "a"; }; }, { a: "a"; }>, "foo">'. Types of property 'a' are incompatible. Type '{ b: "a"; }' is not assignable to type '"a"'.
 
// ✅ `ctx.a` overlaps from `barMiddleware` and `fooMiddleware`
barMiddleware.unstable_pipe(fooMiddleware);