splitLink
Send each call down one of two chains, picked from its path, type or input.
On this page
splitLink({ condition, true, false }) sends a call down the true chain when condition returns true for it, and down false otherwise. Each branch is a link or an array of links. On a client made with router:, condition sees typed paths:
import {
function createTrpcClient<TSource, const TLinks extends ReadonlyArray<TrpcLink<any, RouterOf<TSource>>>>(opts: TypedClientOptions<TSource, TLinks> & DuplicateSwitchCheck<TLinks> & UnmetNeedCheck<TLinks>): TrpcClient<RouterOf<TSource>, LinksContext<TLinks>, undefined, LinksTypes<TLinks>>createTrpcClient,
function httpLink<TOpts extends HttpLinkOptions>(opts: TOpts): TrpcLink<HttpLinkDecl<TOpts>>httpLink,
function routerType<TRouter>(): RouterType<TRouter>routerType,
function splitLink<TRouter = any, TTrue extends Chain = Chain, TFalse extends Chain = Chain>(opts: SplitLinkOptions<TRouter, TTrue, TFalse>): TrpcLink<BranchesDecl<{
true: TTrue;
false: TFalse;
}>, TRouter>
splitLink,
function wsLink<TOpts extends WebSocketLinkOptions>(opts: TOpts): SocketLink<{
form: FormOfOptions<TOpts>;
}>
wsLink,
} from '@trpc12/trpc/client';
const const client: TrpcClient<{
post: {
byId: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: {
id: string;
};
output: Post;
errors: TrpcError<"NOT_FOUND", {
id: string;
}> | SchemaValidationError<ZodObject<{
id: ZodString;
}, $strip>>;
services: never;
}>;
list: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: undefined;
output: Post[];
errors: never;
services: never;
}>;
create: Procedure<{
type: "mutation";
ctx: Context;
meta: {};
input: {
title: string;
};
output: Post;
errors: TrpcError<...> | SchemaValidationError<...>;
services: never;
}>;
};
}, {}, undefined, LinksTypes<...>>
client = createTrpcClient<RouterType<{
post: {
byId: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: {
id: string;
};
output: Post;
errors: TrpcError<"NOT_FOUND", {
id: string;
}> | SchemaValidationError<ZodObject<{
id: ZodString;
}, $strip>>;
services: never;
}>;
list: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: undefined;
output: Post[];
errors: never;
services: never;
}>;
create: Procedure<{
type: "mutation";
ctx: Context;
meta: {};
input: {
title: string;
};
output: Post;
errors: TrpcError<...> | SchemaValidationError<...>;
services: never;
}>;
};
}>, readonly [...]>(opts: TypedClientOptions<...>): TrpcClient<...>
createTrpcClient({
TypedClientOptions<RouterType<{ post: { byId: Procedure<{ type: "query"; ctx: Context; meta: {}; input: { id: string; }; output: Post; errors: TrpcError<"NOT_FOUND", { id: string; }> | SchemaValidationError<ZodObject<{ id: ZodString; }, $strip>>; services: never; }>; list: Procedure<...>; create: Procedure<...>; }; }>, readonly [...]>.router: RouterType<{
post: {
byId: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: {
id: string;
};
output: Post;
errors: TrpcError<"NOT_FOUND", {
id: string;
}> | SchemaValidationError<ZodObject<{
id: ZodString;
}, $strip>>;
services: never;
}>;
list: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: undefined;
output: Post[];
errors: never;
services: never;
}>;
create: Procedure<{
type: "mutation";
ctx: Context;
meta: {};
input: {
title: string;
};
output: Post;
errors: TrpcError<...> | SchemaValidationError<...>;
services: never;
}>;
};
}>
router: routerType<{
post: {
byId: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: {
id: string;
};
output: Post;
errors: TrpcError<"NOT_FOUND", {
id: string;
}> | SchemaValidationError<ZodObject<{
id: ZodString;
}, $strip>>;
services: never;
}>;
list: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: undefined;
output: Post[];
errors: never;
services: never;
}>;
create: Procedure<{
type: "mutation";
ctx: Context;
meta: {};
input: {
title: string;
};
output: Post;
errors: TrpcError<...> | SchemaValidationError<...>;
services: never;
}>;
};
}>(): RouterType<...>
routerType<type AppRouter = {
post: {
byId: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: {
id: string;
};
output: Post;
errors: TrpcError<"NOT_FOUND", {
id: string;
}> | SchemaValidationError<ZodObject<{
id: ZodString;
}, $strip>>;
services: never;
}>;
list: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: undefined;
output: Post[];
errors: never;
services: never;
}>;
create: Procedure<{
type: "mutation";
ctx: Context;
meta: {};
input: {
title: string;
};
output: Post;
errors: TrpcError<...> | SchemaValidationError<...>;
services: never;
}>;
};
}
AppRouter>(),
TypedClientOptions<RouterType<{ post: { byId: Procedure<{ type: "query"; ctx: Context; meta: {}; input: { id: string; }; output: Post; errors: TrpcError<"NOT_FOUND", { id: string; }> | SchemaValidationError<ZodObject<{ id: ZodString; }, $strip>>; services: never; }>; list: Procedure<...>; create: Procedure<...>; }; }>, readonly [...]>.links: readonly [TrpcLink<BranchesDecl<{
true: SocketLink<{
form: JsonForm;
}>;
false: TrpcLink<HttpLinkDecl<{
url: string;
batch: true;
}>, any>;
}>, {
post: {
byId: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: {
id: string;
};
output: Post;
errors: TrpcError<"NOT_FOUND", {
id: string;
}> | SchemaValidationError<ZodObject<{
id: ZodString;
}, $strip>>;
services: never;
}>;
list: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: undefined;
output: Post[];
errors: never;
services: never;
}>;
create: Procedure<{
type: "mutation";
ctx: Context;
meta: {};
input: {
title: string;
};
output: Post;
errors: TrpcError<...> | SchemaValidationError<...>;
services: never;
}>;
};
}>]
links: [
splitLink<{
post: {
byId: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: {
id: string;
};
output: Post;
errors: TrpcError<"NOT_FOUND", {
id: string;
}> | SchemaValidationError<ZodObject<{
id: ZodString;
}, $strip>>;
services: never;
}>;
list: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: undefined;
output: Post[];
errors: never;
services: never;
}>;
create: Procedure<{
type: "mutation";
ctx: Context;
meta: {};
input: {
title: string;
};
output: Post;
errors: TrpcError<...> | SchemaValidationError<...>;
services: never;
}>;
};
}, SocketLink<...>, TrpcLink<...>>(opts: SplitLinkOptions<...>): TrpcLink<...>
splitLink({
SplitLinkOptions<{ post: { byId: Procedure<{ type: "query"; ctx: Context; meta: {}; input: { id: string; }; output: Post; errors: TrpcError<"NOT_FOUND", { id: string; }> | SchemaValidationError<ZodObject<{ id: ZodString; }, $strip>>; services: never; }>; list: Procedure<...>; create: Procedure<...>; }; }, SocketLink<...>, TrpcLink<...>>.condition: (op: Operation<{}> & {
readonly path: "post.byId" | "post.list" | "post.create";
}) => boolean
condition: (op: Operation<{}> & {
readonly path: "post.byId" | "post.list" | "post.create";
}
op) => op: Operation<{}> & {
readonly path: "post.byId" | "post.list" | "post.create";
}
op.Operation<{}>.type: ProcedureTypetype === 'subscription',
SplitLinkOptions<{ post: { byId: Procedure<{ type: "query"; ctx: Context; meta: {}; input: { id: string; }; output: Post; errors: TrpcError<"NOT_FOUND", { id: string; }> | SchemaValidationError<ZodObject<{ id: ZodString; }, $strip>>; services: never; }>; list: Procedure<...>; create: Procedure<...>; }; }, SocketLink<...>, TrpcLink<...>>.true: SocketLink<{
form: JsonForm;
}>
true: wsLink<{
url: string;
}>(opts: {
url: string;
}): SocketLink<{
form: JsonForm;
}>
wsLink({ url: stringurl: 'ws://localhost:3000/trpc' }),
SplitLinkOptions<{ post: { byId: Procedure<{ type: "query"; ctx: Context; meta: {}; input: { id: string; }; output: Post; errors: TrpcError<"NOT_FOUND", { id: string; }> | SchemaValidationError<ZodObject<{ id: ZodString; }, $strip>>; services: never; }>; list: Procedure<...>; create: Procedure<...>; }; }, SocketLink<...>, TrpcLink<...>>.false: TrpcLink<HttpLinkDecl<{
url: string;
batch: true;
}>, any>
false: httpLink<{
url: string;
batch: true;
}>(opts: {
url: string;
batch: true;
}): TrpcLink<HttpLinkDecl<{
url: string;
batch: true;
}>, any>
httpLink({ url: stringurl: 'http://localhost:3000/trpc', batch: truebatch: true }),
}),
],
});Calls get the call options and errors that the links of either branch declare. An operation type is missing only if every branch lacks it, and the link provides only what every branch provides (Custom links). For more than two branches, or to let a call pick its branch, use switchLink.
One client, several backends
A link can change the operation it passes on. That lets one client cover routers served by different backends, even ones with different contexts:
const const unprefix: (prefix: string) => TrpcLink<{}, any>unprefix = (prefix: stringprefix: string) =>
link<{}>(fn: (opts: EffectLinkOpts<{}>) => OperationStream): TrpcLink<{}, any>link((opts: EffectLinkOpts<{}>opts) =>
opts: EffectLinkOpts<{}>opts.EffectLinkOpts<{}>.next: (op: Operation) => OperationStreamnext({ ...opts: EffectLinkOpts<{}>opts.EffectLinkOpts<{}>.op: Operation<{}>op, Operation<{}>.path: stringpath: opts: EffectLinkOpts<{}>opts.EffectLinkOpts<{}>.op: Operation<{}>op.Operation<{}>.path: stringpath.String.slice(start?: number, end?: number): stringslice(prefix: stringprefix.String.length: numberlength + 1) }),
);
createTrpcClient<RouterType<{
blog: BlogRouter;
shop: ShopRouter;
}>, readonly [TrpcLink<BranchesDecl<{
true: (TrpcLink<{}, any> | TrpcLink<{
form: JsonForm;
provides: "response";
}, any>)[];
false: (TrpcLink<{}, any> | TrpcLink<{
form: JsonForm;
provides: "response";
}, any>)[];
}>, {
blog: BlogRouter;
shop: ShopRouter;
}>]>(opts: TypedClientOptions<RouterType<{
blog: BlogRouter;
shop: ShopRouter;
}>, readonly [TrpcLink<BranchesDecl<{
true: (TrpcLink<{}, any> | TrpcLink<{
form: JsonForm;
provides: "response";
}, any>)[];
false: (TrpcLink<{}, any> | TrpcLink<{
form: JsonForm;
provides: "response";
}, any>)[];
}>, {
blog: BlogRouter;
shop: ShopRouter;
}>]>): TrpcClient<...>
createTrpcClient({
TypedClientOptions<RouterType<{ blog: BlogRouter; shop: ShopRouter; }>, readonly [TrpcLink<BranchesDecl<{ true: (TrpcLink<{}, any> | TrpcLink<{ form: JsonForm; provides: "response"; }, any>)[]; false: (TrpcLink<...> | TrpcLink<...>)[]; }>, { blog: BlogRouter; shop: ShopRouter; }>]>.router: RouterType<{
blog: BlogRouter;
shop: ShopRouter;
}>
router: routerType<{
blog: BlogRouter;
shop: ShopRouter;
}>(): RouterType<{
blog: BlogRouter;
shop: ShopRouter;
}>
routerType<{ blog: {
post: {
byId: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: {
id: string;
};
output: Post;
errors: TrpcError<"NOT_FOUND", {
id: string;
}> | SchemaValidationError<ZodObject<{
id: ZodString;
}, $strip>>;
services: never;
}>;
list: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: undefined;
output: Post[];
errors: never;
services: never;
}>;
create: Procedure<{
type: "mutation";
ctx: Context;
meta: {};
input: {
title: string;
};
output: Post;
errors: TrpcError<...> | SchemaValidationError<...>;
services: never;
}>;
};
}
blog: type BlogRouter = {
post: {
byId: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: {
id: string;
};
output: Post;
errors: TrpcError<"NOT_FOUND", {
id: string;
}> | SchemaValidationError<ZodObject<{
id: ZodString;
}, $strip>>;
services: never;
}>;
list: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: undefined;
output: Post[];
errors: never;
services: never;
}>;
create: Procedure<{
type: "mutation";
ctx: Context;
meta: {};
input: {
title: string;
};
output: Post;
errors: TrpcError<...> | SchemaValidationError<...>;
services: never;
}>;
};
}
BlogRouter; shop: {
cart: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: undefined;
output: string[];
errors: never;
services: never;
}>;
}
shop: type ShopRouter = {
cart: Procedure<{
type: "query";
ctx: Context;
meta: {};
input: undefined;
output: string[];
errors: never;
services: never;
}>;
}
ShopRouter }>(),
TypedClientOptions<RouterType<{ blog: BlogRouter; shop: ShopRouter; }>, readonly [TrpcLink<BranchesDecl<{ true: (TrpcLink<{}, any> | TrpcLink<{ form: JsonForm; provides: "response"; }, any>)[]; false: (TrpcLink<...> | TrpcLink<...>)[]; }>, { blog: BlogRouter; shop: ShopRouter; }>]>.links: readonly [TrpcLink<BranchesDecl<{
true: (TrpcLink<{}, any> | TrpcLink<{
form: JsonForm;
provides: "response";
}, any>)[];
false: (TrpcLink<{}, any> | TrpcLink<{
form: JsonForm;
provides: "response";
}, any>)[];
}>, {
blog: BlogRouter;
shop: ShopRouter;
}>]
links: [
splitLink<{
blog: BlogRouter;
shop: ShopRouter;
}, (TrpcLink<{}, any> | TrpcLink<{
form: JsonForm;
provides: "response";
}, any>)[], (TrpcLink<{}, any> | TrpcLink<{
form: JsonForm;
provides: "response";
}, any>)[]>(opts: SplitLinkOptions<{
blog: BlogRouter;
shop: ShopRouter;
}, (TrpcLink<{}, any> | TrpcLink<{
form: JsonForm;
provides: "response";
}, any>)[], (TrpcLink<{}, any> | TrpcLink<{
form: JsonForm;
provides: "response";
}, any>)[]>): TrpcLink<...>
splitLink({
SplitLinkOptions<{ blog: BlogRouter; shop: ShopRouter; }, (TrpcLink<{}, any> | TrpcLink<{ form: JsonForm; provides: "response"; }, any>)[], (TrpcLink<{}, any> | TrpcLink<...>)[]>.condition: (op: Operation<{}> & {
readonly path: "shop.cart" | "blog.post.byId" | "blog.post.list" | "blog.post.create";
}) => boolean
condition: (op: Operation<{}> & {
readonly path: "shop.cart" | "blog.post.byId" | "blog.post.list" | "blog.post.create";
}
op) => op: Operation<{}> & {
readonly path: "shop.cart" | "blog.post.byId" | "blog.post.list" | "blog.post.create";
}
op.path: "shop.cart" | "blog.post.byId" | "blog.post.list" | "blog.post.create"path.String.startsWith(searchString: string, position?: number): booleanstartsWith('shop.'),
SplitLinkOptions<{ blog: BlogRouter; shop: ShopRouter; }, (TrpcLink<{}, any> | TrpcLink<{ form: JsonForm; provides: "response"; }, any>)[], (TrpcLink<{}, any> | TrpcLink<...>)[]>.true: (TrpcLink<{}, any> | TrpcLink<{
form: JsonForm;
provides: "response";
}, any>)[]
true: [const unprefix: (prefix: string) => TrpcLink<{}, any>unprefix('shop'), httpLink<{
url: string;
}>(opts: {
url: string;
}): TrpcLink<{
form: JsonForm;
provides: "response";
}, any>
httpLink({ url: stringurl: const shopUrl: stringshopUrl })],
SplitLinkOptions<{ blog: BlogRouter; shop: ShopRouter; }, (TrpcLink<{}, any> | TrpcLink<{ form: JsonForm; provides: "response"; }, any>)[], (TrpcLink<{}, any> | TrpcLink<...>)[]>.false: (TrpcLink<{}, any> | TrpcLink<{
form: JsonForm;
provides: "response";
}, any>)[]
false: [const unprefix: (prefix: string) => TrpcLink<{}, any>unprefix('blog'), httpLink<{
url: string;
}>(opts: {
url: string;
}): TrpcLink<{
form: JsonForm;
provides: "response";
}, any>
httpLink({ url: stringurl: const blogUrl: stringblogUrl })],
}),
],
});