or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdclient-creation.mderror-handling.mdhttp-links.mdindex.mdutility-links.mdwebsocket-links.md

client-creation.mddocs/

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.