SDKs & Developer Experience

Type Safety with the Claude SDK: TypeScript, Java, and C#

In a typed language, the SDK is more than a convenience — it's a compile-time contract that catches malformed requests and unhandled response shapes before they reach production.

Claude 3P 101 · Updated July 2026 · Unofficial guide

Enterprises with large TypeScript, Java, or C# codebases usually ask the same question about an API client: does it give the compiler enough information to catch mistakes? For the official Claude SDKs the answer is yes — request parameters and response objects are fully typed — and the interesting part is where that typing earns its keep: the response's content structure, which is a list of differently-shaped blocks rather than a single string.

The shape problem the types solve

A Claude response's content is a sequence of typed blocks: plain text blocks, and — once you use tool calling — tool_use blocks carrying a tool name and structured input. Code that assumes "the response is text" breaks the day someone enables tools. Typed SDKs model this as a tagged union (a "discriminated union" in TypeScript terms): each block carries a type tag, and the compiler forces you to check the tag before touching tag-specific fields. That turns "we forgot to handle tool calls" from a runtime surprise into a compile error. The precise type names differ per SDK, so treat each repository's README and generated API docs as the reference — TypeScript, Java, and C# — rather than transliterating names between languages.

The same discipline applies to stop_reason: recent models can end a response with values like "refusal" or "model_context_window_exceeded", and exhaustive handling of that enum (a switch the compiler checks) is precisely what typed languages are for.

TypeScript

Install with npm install @anthropic-ai/sdk. The minimal client is:

import Anthropic from '@anthropic-ai/sdk';

const client = new Anthropic({
  apiKey: process.env['ANTHROPIC_API_KEY'],
});

From there, await client.messages.create({...}) returns a typed message object, and narrowing on each content block's type tag is idiomatic TypeScript — inside the narrowed branch, the compiler knows exactly which fields exist. With strictNullChecks on, optional response fields must be handled explicitly, which is exactly the null-safety you want at an API boundary. The SDK supports Node.js 20 LTS+, Deno, Bun, Cloudflare Workers, and Vercel Edge; browser use is disabled by default (shipping an API key to a browser is an anti-pattern anyway).

Java

The Java SDK (com.anthropic:anthropic-java, Java 8+, MIT-licensed) separates the transport from the interface: you build an AnthropicOkHttpClient — via AnthropicOkHttpClient.fromEnv(), which reads ANTHROPIC_API_KEY or the anthropic.apiKey system property, or explicitly with AnthropicOkHttpClient.builder().apiKey(...).build() — and receive an AnthropicClient interface to program against. Requests use builder-pattern parameter objects: client.messages().create(params) with a MessageCreateParams built fluently, so required fields are enforced at build time rather than discovered as 400 errors. Response unions surface through accessor and visitor patterns idiomatic to Java; the repository documentation shows the current idiom for iterating content blocks safely.

C#

The C# SDK is the official Anthropic NuGet package (dotnet add package Anthropic, .NET Standard 2.0+). One procurement-relevant note: it became the official SDK as of version 10 — earlier versions of that package lineage were community-maintained under a different name, so pin to a current major version. Client setup is minimal — AnthropicClient client = new(); reads ANTHROPIC_API_KEY from the environment — and calls are async-first: await client.Messages.Create(parameters). With nullable reference types enabled in your project, optional response fields participate in C#'s null-flow analysis, and pattern matching over content block types gives you the same tag-checked handling as TypeScript's unions.

Rule of thumb: in all three languages, make one exhaustive content-block handler and one exhaustive stop_reason handler, and route every response through them. When an SDK upgrade introduces a new block type or stop reason, the compiler — not an incident report — tells you where to look.

Where to go next

Language setup lives in the TypeScript, Java, and C# quickstarts. For what happens when types meet failures, see error handling patterns across SDK languages, and pinning SDK versions covers upgrade discipline.

Sources