0
# Client Creation
1
2
Core client factory functions for creating type-safe and untyped tRPC clients with configurable transport links.
3
4
## Capabilities
5
6
### createTRPCClient
7
8
Creates a type-safe tRPC client with full TypeScript inference from your router definition. This is the primary way to create a tRPC client that provides compile-time type safety and IntelliSense support.
9
10
```typescript { .api }
11
/**
12
* Creates a type-safe tRPC client with full TypeScript inference
13
* @param opts - Configuration options including links array
14
* @returns Typed proxy client with router-specific methods
15
*/
16
function createTRPCClient<TRouter extends AnyRouter>(
17
opts: CreateTRPCClientOptions<TRouter>
18
): TRPCClient<TRouter>;
19
20
interface CreateTRPCClientOptions<TRouter> {
21
/** Array of transport and middleware links to compose together */
22
links: TRPCLink<TRouter>[];
23
}
24
25
type TRPCClient<TRouter extends AnyRouter> = DecoratedProcedureRecord<
26
{
27
transformer: TRouter['_def']['_config']['$types']['transformer'];
28
errorShape: TRouter['_def']['_config']['$types']['errorShape'];
29
},
30
TRouter['_def']['record']
31
>;
32
```
33
34
**Usage Examples:**
35
36
```typescript
37
import { createTRPCClient, httpBatchLink } from "@trpc/client";
38
import type { AppRouter } from "./server";
39
40
// Basic client with HTTP batching
41
const client = createTRPCClient<AppRouter>({
42
links: [
43
httpBatchLink({
44
url: "http://localhost:3000/trpc",
45
}),
46
],
47
});
48
49
// Multi-link chain with logging and HTTP transport
50
const client = createTRPCClient<AppRouter>({
51
links: [
52
loggerLink({
53
enabled: (op) => op.direction === 'down' && op.result instanceof Error,
54
}),
55
httpBatchLink({
56
url: "http://localhost:3000/trpc",
57
headers() {
58
return {
59
authorization: getAuthHeader(),
60
};
61
},
62
}),
63
],
64
});
65
66
// Using the typed client
67
const user = await client.user.getById.query({ id: 1 });
68
const result = await client.posts.create.mutate({
69
title: "Hello World",
70
content: "My first post",
71
});
72
```
73
74
### createTRPCUntypedClient
75
76
Creates an untyped client for dynamic operations without compile-time type safety. Useful for scenarios where you need to make dynamic requests or when working with multiple router types.
77
78
```typescript { .api }
79
/**
80
* Creates an untyped client for low-level operations
81
* @param opts - Configuration options including links array
82
* @returns Untyped client with query, mutation, and subscription methods
83
*/
84
function createTRPCUntypedClient<TRouter extends AnyRouter>(
85
opts: CreateTRPCClientOptions<TRouter>
86
): TRPCUntypedClient<TRouter>;
87
88
class TRPCUntypedClient<TInferrable extends InferrableClientTypes> {
89
/** Execute a query operation */
90
query(path: string, input?: unknown, opts?: TRPCRequestOptions): Promise<unknown>;
91
92
/** Execute a mutation operation */
93
mutation(path: string, input?: unknown, opts?: TRPCRequestOptions): Promise<unknown>;
94
95
/** Subscribe to a subscription operation */
96
subscription(
97
path: string,
98
input: unknown,
99
opts: Partial<TRPCSubscriptionObserver<unknown, TRPCClientError<any>>> & TRPCRequestOptions
100
): Unsubscribable;
101
102
/** Runtime configuration available to links */
103
readonly runtime: TRPCClientRuntime;
104
}
105
```
106
107
**Usage Examples:**
108
109
```typescript
110
import { createTRPCUntypedClient, httpLink } from "@trpc/client";
111
112
const client = createTRPCUntypedClient({
113
links: [
114
httpLink({
115
url: "http://localhost:3000/trpc",
116
}),
117
],
118
});
119
120
// Dynamic query execution
121
const user = await client.query("user.getById", { id: 1 });
122
123
// Dynamic mutation execution
124
const result = await client.mutation("posts.create", {
125
title: "Dynamic Post",
126
content: "Created without type safety",
127
});
128
129
// Dynamic subscription
130
const unsubscribe = client.subscription("posts.onUpdate", undefined, {
131
onData: (data) => console.log("Post updated:", data),
132
onError: (err) => console.error("Subscription error:", err),
133
});
134
```
135
136
### Request Options
137
138
Configuration options for individual requests to control context and cancellation.
139
140
```typescript { .api }
141
interface TRPCRequestOptions {
142
/** Pass additional context to links */
143
context?: OperationContext;
144
/** Abort signal for request cancellation */
145
signal?: AbortSignal;
146
}
147
148
interface TRPCProcedureOptions {
149
/** Client-side context data */
150
context?: Record<string, unknown>;
151
/** Abort signal for request cancellation */
152
signal?: AbortSignal;
153
}
154
155
/** Context passed between links in the chain */
156
type OperationContext = Record<string, unknown>;
157
```
158
159
**Usage Examples:**
160
161
```typescript
162
// Using request options with typed client
163
const controller = new AbortController();
164
const user = await client.user.getById.query(
165
{ id: 1 },
166
{
167
context: { priority: 'high' },
168
signal: controller.signal,
169
}
170
);
171
172
// Cancel the request
173
controller.abort();
174
175
// Using request options with untyped client
176
const result = await untypedClient.query(
177
"user.getById",
178
{ id: 1 },
179
{
180
context: { requestId: 'req-123' },
181
signal: new AbortController().signal,
182
}
183
);
184
```
185
186
### Subscription Observer
187
188
Interface for handling subscription events and state changes.
189
190
```typescript { .api }
191
interface TRPCSubscriptionObserver<TValue, TError> {
192
/** Called when subscription starts */
193
onStarted: (opts: { context: OperationContext | undefined }) => void;
194
195
/** Called for each data emission */
196
onData: (value: inferAsyncIterableYield<TValue>) => void;
197
198
/** Called when subscription encounters an error */
199
onError: (err: TError) => void;
200
201
/** Called when subscription is manually stopped */
202
onStopped: () => void;
203
204
/** Called when subscription completes naturally */
205
onComplete: () => void;
206
207
/** Called when connection state changes (WebSocket reconnection, etc.) */
208
onConnectionStateChange: (state: TRPCConnectionState<TError>) => void;
209
}
210
211
/** Represents an active subscription that can be cancelled */
212
interface Unsubscribable {
213
unsubscribe(): void;
214
}
215
```
216
217
**Usage Examples:**
218
219
```typescript
220
// Complete subscription observer
221
const unsubscribe = client.posts.onUpdate.subscribe(undefined, {
222
onStarted: ({ context }) => {
223
console.log("Subscription started with context:", context);
224
},
225
onData: (post) => {
226
console.log("Received post update:", post);
227
updateUI(post);
228
},
229
onError: (err) => {
230
console.error("Subscription error:", err);
231
showErrorMessage(err.message);
232
},
233
onStopped: () => {
234
console.log("Subscription stopped");
235
},
236
onComplete: () => {
237
console.log("Subscription completed");
238
},
239
onConnectionStateChange: (state) => {
240
if (state.type === 'connecting') {
241
console.log("Reconnecting to server...");
242
}
243
},
244
});
245
246
// Clean up subscription
247
unsubscribe.unsubscribe();
248
```
249
250
### Utility Functions
251
252
Additional utility functions for client management and inspection.
253
254
```typescript { .api }
255
/**
256
* Extract untyped client from typed proxy client (internal utility)
257
* @param client - Typed tRPC client
258
* @returns Underlying untyped client instance
259
*/
260
function getUntypedClient<TRouter extends AnyRouter>(
261
client: TRPCClient<TRouter>
262
): TRPCUntypedClient<TRouter>;
263
```
264
265
**Usage Examples:**
266
267
```typescript
268
import { createTRPCClient, getUntypedClient, httpBatchLink } from "@trpc/client";
269
270
const typedClient = createTRPCClient<AppRouter>({
271
links: [httpBatchLink({ url: "http://localhost:3000/trpc" })],
272
});
273
274
// Access untyped client for dynamic operations
275
const untypedClient = getUntypedClient(typedClient);
276
277
// Mix typed and untyped operations
278
const typedResult = await typedClient.user.getById.query({ id: 1 });
279
const dynamicResult = await untypedClient.query("user.search", { term: "alice" });
280
```
281
282
### Deprecated APIs
283
284
Legacy client creation functions maintained for backward compatibility.
285
286
```typescript { .api }
287
/**
288
* @deprecated use createTRPCClient instead, will be removed in v12
289
*/
290
const createTRPCProxyClient = createTRPCClient;
291
292
/**
293
* @deprecated use inferRouterClient instead, will be removed in v12
294
*/
295
type inferRouterProxyClient<TRouter extends AnyRouter> = TRPCClient<TRouter>;
296
297
/**
298
* @deprecated use TRPCClient instead, will be removed in v12
299
*/
300
type CreateTRPCClient<TRouter extends AnyRouter> = TRPCClient<TRouter>;
301
```
302
303
These deprecated exports are aliases that will be removed in future versions. Update your code to use the new API names for forward compatibility.