Design APIs Effortlessly with TypeSpec: Say Goodbye to Maintaining Thousand-Line OpenAPI Files

Development tutorial - IT technology blog
Development tutorial - IT technology blog

The Nightmare of ‘Manual OpenAPI’

Writing a 3,000-line openapi.yaml file by hand is the fastest way to drain a developer’s patience. If you’ve ever forgotten to update a field across dozens of endpoints, you know the frustration of data inconsistencies when the Frontend calls an API and the response doesn’t match the documentation. Bulky YAML syntax, repetitive structures, and the difficulty of reusing schemas are major hurdles in complex microservices projects.

After 6 months of using TypeSpec in production, I’ve realized it’s a true lifesaver for the API-first workflow. Instead of laboriously typing YAML, I write code with a concise syntax similar to TypeScript. This tool automatically renders everything from Swagger docs to Client SDKs. In my team’s experience, TypeSpec has helped cut down data structure synchronization meetings between Backend and Frontend by up to 70%.

TypeSpec: When TypeScript and API Design Join Forces

TypeSpec is an Interface Description Language (IDL) developed by Microsoft. You can think of it as a version of TypeScript specifically designed for API design. It allows you to define models, endpoints, and data constraints with just a few lines of concise code.

The greatest strength of TypeSpec lies in its ability to create a Single Source of Truth. From a single .tsp file, you can export to various formats:

  • OpenAPI 3.0/3.1 for Swagger documentation.
  • JSON Schema for input data validation.
  • Client SDKs for multiple languages (C#, Java, Python, TypeScript).
  • Protobuf for systems using gRPC.

Hands-on: Building Your First API in 5 Minutes

To get started, make sure you have NodeJS installed. Installing the TypeSpec compiler takes just one npm command:

npm install -g @typespec/compiler

Next, initialize a new project:

mkdir my-api-design && cd my-api-design
tsp init

When prompted, choose the @typespec/openapi3 template. This is the most common choice for creating standardized API documentation.

Writing TypeSpec Code Instead of YAML

Let’s try designing a blog post management API. You’ll see that TypeSpec syntax is much clearer and more coherent than the curly-brace mess of JSON:

import "@typespec/http";
import "@typespec/rest";
import "@typespec/openapi3";

using TypeSpec.Http;
using TypeSpec.Rest;

@service({
  title: "Blog Service",
})
@server("https://api.itfromzero.com", "Production server")
namespace Blog;

model Post {
  @visibility("read")
  id: string;

  @minLength(5)
  title: string;

  content: string;
  status: "draft" | "published";
  createdAt: utcDateTime;
}

@route("/posts")
interface Posts {
  @get list(): Post[];
  
  @post create(@body post: Post): Post | { @statusCode statusCode: 400, message: string };

  @get read(@path id: string): Post | { @statusCode statusCode: 404 };
}

The code above defines a model Post with validations like @minLength. The Posts interface contains the corresponding HTTP methods. You no longer have to worry about annoying indentation issues as you do in YAML.

Automating Documentation Export

Once the design is complete, simply run the following command to generate a professional openapi.yaml file:

tsp compile .

The result will appear in the tsp-output directory. While working, if I need to quickly format data or check JSON, I often use toolcraft.app. This tool helps process resulting JSON snippets quickly without slowing down my machine with too many VS Code extensions.

Solving the ‘Out of Sync’ Issue with Client SDKs

Trouble often arises when the Backend changes a field but the Frontend remains unaware. With TypeSpec, you can use Emitters to automatically generate code for the frontend.

Installing the emitter for TypeScript is very simple:

npm install @azure-tools/typespec-ts

Then, configure it in your tspconfig.yaml file. When you compile, TypeSpec will generate all the interfaces and API call functions. The Frontend team only needs to import this package to get accurate IntelliSense code suggestions. Errors caused by typing the wrong field name are virtually eliminated.

Hard-earned Lessons from Real Projects

After six months of implementation, I’ve drawn three important lessons to optimize the workflow:

  1. Don’t let documentation be “silent”: Use the @doc decorator to describe each field in detail. These descriptions will appear directly on the Swagger UI, helping other developers understand the API without needing to ask you.
  2. Modularize everything: Group shared models like ErrorResponse or Pagination into a common.tsp file. This helps you manage dozens of microservices without code duplication.
  3. Integrate CI/CD into the workflow: Set up your system to automatically run tsp compile on every Pull Request. If the .tsp file has errors, the build will fail immediately, preventing incorrect documentation from being pushed to the system.

TypeSpec’s linting capabilities are truly valuable. If you accidentally define two endpoints with the same route, the compiler will throw an error immediately. You catch mistakes while writing code instead of panicking after deployment because the documentation is a mess.

Conclusion

TypeSpec is not just a new tool; it completely changes how we think about system design. It bridges the gap between design and implementation. Whether your project is a small startup or an enterprise system, investing in TypeSpec will save you a lot of manual labor as the project scales. Stop wasting time manually fixing YAML files—try TypeSpec and feel the difference today!

Share: