A step-by-step guide on how to automatically create strongly typed TypeScript client for your .NET API service.
Creating Demo API
First, let's demonstrate how to create an API. All examples are provided using console utilities, but they can be reproduced using IDE of choice.
Let's create a solution for our application:
dotnet new sln - name OpenApiDemo
Creating a full-scale WebAPI project with controllers:
dotnet new webapi -use-controllers -n DemoApi
And let's add it to our solution:
dotnet sln add DemoApi
As a result, you will have file structure like this:
Adding OpenAPI and Scalar
Recently, Microsoft introduced their own API description generator, reducing the reliance on Swashbuckle Swagger. Although this decision generated some controversy, considering the recent commercialization of many free libraries such as MassTransit and AutoMapper, it may not be entirely unfavorable. It's 2025 after all, so no need to depend on swagger.
So, let's add an OpenApi package to our dotnet project:
dotnet add DemoApi package Microsoft.AspNetCore.OpenApi
And also let's add Scalar to test our API (it's not actually needed to create typescript client, but it's always nice to have).
dotnet add DemoApi package Scalar.AspNetCore
And, also, we need to setup scalar to communicate with openapi generated references:
builder.Services.AddControllers();
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
app.MapScalarApiReference();
}
Let's run our API and see if everything is OK:
dotnet run --project DemoApi
Generating OpenAPI reference file on build
Fine! Now we need to get api description file on build. To do this we need to install Microsoft.Extensions.ApiDescription.Server package by following command:
dotnet add DemoApi package Microsoft.Extensions.ApiDescription.Server
Ok, let's build project
dotnet build DemoApi
After building there should be a file DemoApi.json inside obj folder of your project
Regrettably, the DemoApi.json file is generated exclusively within the obj folder. For those utilizing a CI/CD pipeline where the backend and frontend are built in separate steps, and the output from the backend build is limited to the bin folder or, in some cases, only the docker image.
There are two potential solutions: either copy this file during the CI/CD step or modify your .csproj file accordingly. Given that MSBuild can be complex, here is the code that needs to be added:
<Target Name="PostBuild" AfterTargets="Build">
<Copy SourceFiles="$(ProjectDir)obj\DemoAPI.json" DestinationFolder="$(OutDir)" />
<Message Text="open api file copiied to $(OutDir)" Importance="high"/>
</Target>
<Target Name="CopyFilesToPublish" AfterTargets="Publish">
<Copy SourceFiles="$(OutDir)\DemoAPI.json" DestinationFolder="$(PublishDir)"/>
</Target>
Command to test those adjustments:
dotnet publish DemoApi -o out
Front-end
Front-end Preparations:
We will be using orval to generate our client, primarily because it comes highly recommended by my front-end coworkers.
Some preparational steps:
mkdir Front
cd Front
npm init
npm i orval -D
npm i axios
TypeScript client generation:
Create orval.config.js (this one generates client that uses axios library to make calls. If you want to use fetch api see documentation):
module.exports = {
weather: {
input: {
target: "../out/DemoAPI.json",
},
output: {
mode: "split",
target: "endpoint.ts",
schemas: "model",
},
},
};
To generate your typescript client, use command:
node .\node_modules\orval\dist\bin\orval.js --config .\orval.config.js
That's it. Your typescript client file is in endpoint.ts, and types for API contract calls are in models folder.
If you need a source code for this tutorial, I had created a github repository.
Btw, you can subscribe to my medium blog, to get my posts faster.