Skip to content

Migrating to TypeSpec

Maor Leger edited this page Aug 1, 2025 · 7 revisions

This guide helps service teams migrate their JavaScript SDK generation from OpenAPI specifications and AutoRest to TypeSpec. The migration process involves updating how your SDK is generated, but should not result in breaking changes to the public API surface of your SDK.

We expect to complete this guide by end of August 2025. While this guide is being written, feel free to reach out to Maor Leger for support.

Target Audience

This guide is written for service teams who are migrating a high-level client (i.e. a client library with a hand-authored convenience layer) from OpenAPI to TypeSpec.

Overview

TypeSpec is Microsoft's new API specification language that provides better tooling, type safety, and developer experience compared to OpenAPI specifications. When you migrate from AutoRest to TypeSpec:

  • Your public SDK API should remain the same - this is not a breaking change for your customers
  • The generation process changes - you'll use TypeSpec definitions instead of OpenAPI/Swagger files
  • Build scripts and configuration update - new tooling replaces AutoRest
  • Internal generated code structure changes - but your hand-written client code adapts with minimal changes

Prerequisites

Before starting the migration, ensure you have:

  1. TypeSpec definitions ready: Your service's TypeSpec definitions should be complete and merged into the main branch of the Azure REST API specs repository
  2. Local development environment:
  3. Understanding of your current SDK: Know which packages in azure-sdk-for-js belong to your service

Step-by-Step Migration Process

Step 1: Install Required Tools

Install the TypeSpec client generator CLI globally:

npm install -g @azure-tools/[email protected]

For more information on tsp-client, see the TypeSpec Client Generator CLI documentation

Step 2: Initialize TypeSpec Generation

In your package directory (e.g., sdk/your-service/your-package), add the tsp-location.yaml file that points to your TypeSpec definitions in the azure-rest-api-specs repository.

An example tsp-location.yaml file looks like this:

directory: specification/ai/Azure.AI.Projects
commit: a720ec94da68a0d77a691ddd563a4528883638ee
repo: Azure/azure-rest-api-specs

Step 3: Understand the New Generated Structure

After initialization, your package will have a new structure:

sdk/your-service/your-package/
├── src/
│   ├── generated/
│   │   ├── src/           # Generated TypeScript code
│   │   │   ├── api/
│   │   │   ├── models/
│   │   │   ├── index.ts
│   │   │   └── yourServiceClient.ts
│   │   └── tsp-location.yaml
│   ├── index.ts           # Your public exports
│   ├── yourClient.ts      # Your hand-written client code
│   └── ...                # Other hand-written files
├── package.json
└── ...

Key differences from AutoRest:

  • Generated code is now in src/generated/src/ instead of src/generated/
  • The tsp-location.yaml file replaces previous AutoRest configuration
  • Generated models and client interfaces follow TypeScript conventions

Step 4: Update Import Statements

You'll need to update your hand-written client code to import from the new generated structure:

Before (AutoRest):

import { YourServiceClient } from "./generated/yourServiceClient.js";
import { SomeModel } from "./generated/models/index.js";

After (TypeSpec):

import { YourServiceClient } from "./generated/src/yourServiceClient.js";
import { SomeModel } from "./generated/src/models/index.js";

Step 5: Update package.json Scripts

Replace your AutoRest generation script with a TypeSpec generation script:

Before (AutoRest):

{
  "scripts": {
    "generate": "autorest --typescript swagger/README.md"
  }
}

After (TypeSpec):

{
  "scripts": {
    "generate:client": "tsp-client update -d -o src/generated --emitter-options=\"generate-metadata=false;generate-test=false\""
  }
}

The emitter options disable metadata and test generation for HLCs.

skipping metadata generation in tspconfig.yaml must be passed in the command line and not in the tspconfig.yaml file. This is tracked in https://github.com/Azure/azure-rest-api-specs/issues/31610

Step 6: Remove AutoRest Configuration Files

Delete the following files that are no longer needed:

  • swagger/README.md (or similar AutoRest configuration)
  • Any custom AutoRest configuration files
  • Generated files from the old structure (they'll be regenerated in the new location)

Step 9: Test and Validate

  1. Generate the code:

    cd sdk/your-service/your-package
    npm run generate:client
  2. Install dependencies:

    rush update
  3. Build the package:

    rush build -t .
  4. Run tests:

    rushx test
  5. Validate the API surface: Use API Extractor to ensure your public API hasn't changed unexpectedly.

Step 10: Update Generated Code (If Needed)

If the generated code doesn't exactly match your needs, you may need to:

  1. Update your TypeSpec definitions in azure-rest-api-specs
  2. Use emitter customizations in your tspconfig.yaml
  3. Apply post-generation transformations (though this should be rare)

Step 11: Handle Common Migration Issues

Import Path Updates

All imports from generated code need to be updated to include the /src path segment:

// Old
import { Client } from "./generated/client.js";
// New  
import { Client } from "./generated/src/client.js";

Model Changes

TypeSpec may generate slightly different model names or structures. Review the generated models/ directory and update your code accordingly.

Client Configuration

The generated client constructor may have different parameter names or types. Compare the old and new generated client interfaces.

Dependency Updates

Changes to paging

If the generated models do not match convenience / hand-authored models, you may need to adjust your code to accommodate the new structures.

See mapPagedAsyncIterable as an example of a function that can be used to map generated models to your expected structures.

Best Practices

Keeping Generated and Hand-Written Code Separate

  • Never modify files in src/generated/ - they will be overwritten
  • Keep all customizations in your hand-written client files
  • Use TypeScript interfaces and type assertions to bridge any gaps

Version Management

  • Update your package version according to Azure SDK versioning guidelines
  • Add changelog entries describing the migration (usually marked as internal changes)
  • Coordinate with the Azure SDK team for any breaking changes

Testing

  • Ensure all existing tests pass after migration
  • Add tests for any new functionality exposed by TypeSpec
  • Consider adding integration tests to validate against live services

Troubleshooting Common Issues

Generated Code Location

Problem: Cannot find generated types after migration. Solution: Check that imports point to ./generated/src/ instead of ./generated/.

Build Failures

Problem: TypeScript compilation errors after migration. Solution: Run rush update to ensure dependencies are installed, then check import statements.

API Changes

Problem: Generated API doesn't match expectations. Solution: Review your TypeSpec definitions and ensure they're complete. Check emitter options in tspconfig.yaml.

Package.json Script Issues

Problem: npm run generate:client fails. Solution: Ensure @azure-tools/typespec-client-generator-cli is installed globally and tsp-location.yaml exists.

Getting Help

If you encounter issues during migration:

  1. Check existing documentation:

  2. Consult with the team:

    • Post in the TypeSpec Discussion Teams channel
    • Tag @DPG TypeScript for JavaScript/TypeScript-specific questions
  3. File issues:

Clone this wiki locally