NSwag provides comprehensive TypeScript client generation that creates strongly-typed HTTP clients from OpenAPI specifications. The generated clients support multiple frameworks including Angular, React, Vue.js, and vanilla TypeScript with various HTTP libraries.
The main class for generating TypeScript client code.
public class TypeScriptClientGenerator : ClientGeneratorBase<TypeScriptClientGeneratorSettings>
{
public TypeScriptClientGenerator(OpenApiDocument document, TypeScriptClientGeneratorSettings settings);
public string GenerateFile();
public string GenerateClientClass(string controllerName, IEnumerable<OpenApiOperationDescription> operations);
}Comprehensive settings for TypeScript client generation.
public class TypeScriptClientGeneratorSettings : ClientGeneratorBaseSettings
{
// Template and framework
public TypeScriptTemplate Template { get; set; }
public PromiseType PromiseType { get; set; }
public HttpClass HttpClass { get; set; }
public InjectionTokenType InjectionTokenType { get; set; }
public decimal RxJsVersion { get; set; }
// Class and module settings
public string ClassName { get; set; }
public string ModuleName { get; set; }
public string Namespace { get; set; }
public TypeScriptExtensionCode ExtensionCode { get; set; }
// Type generation
public bool GenerateClientClasses { get; set; }
public bool GenerateClientInterfaces { get; set; }
public bool GenerateDtoTypes { get; set; }
public bool GenerateConstructorInterface { get; set; }
// HTTP and request settings
public bool UseTransformOptionsMethod { get; set; }
public bool UseTransformResultMethod { get; set; }
public bool GenerateCallsiteMethods { get; set; }
public string BaseUrlTokenName { get; set; }
public string HttpClientType { get; set; }
// Response handling
public bool UseGetBaseUrlMethod { get; set; }
public bool WithCredentials { get; set; }
public bool GenerateResponseClasses { get; set; }
public string ResponseClass { get; set; }
public bool WrapDtoExceptions { get; set; }
// Serialization and validation
public bool HandleReferences { get; set; }
public bool GenerateCloneMethod { get; set; }
public string QueryNullValue { get; set; }
public bool UseAbortSignal { get; set; }
// Operation naming
public IOperationNameGenerator OperationNameGenerator { get; set; }
public TypeScriptGeneratorSettings TypeScriptGeneratorSettings { get; set; }
}using NSwag;
using NSwag.CodeGeneration.TypeScript;
// Load OpenAPI document
var document = await OpenApiDocument.FromFileAsync("swagger.json");
// Configure settings
var settings = new TypeScriptClientGeneratorSettings
{
ClassName = "ApiClient",
Template = TypeScriptTemplate.Angular
};
// Generate client
var generator = new TypeScriptClientGenerator(document, settings);
string clientCode = generator.GenerateFile();
// Write to file
await File.WriteAllTextAsync("api-client.ts", clientCode);var settings = new TypeScriptClientGeneratorSettings
{
ClassName = "ApiClient",
Template = TypeScriptTemplate.Angular,
HttpClass = HttpClass.HttpClient,
InjectionTokenType = InjectionTokenType.InjectionToken,
// Angular-specific settings
GenerateClientInterfaces = true,
GenerateConstructorInterface = true,
UseTransformOptionsMethod = true,
UseTransformResultMethod = true,
// HTTP settings
WithCredentials = false,
UseAbortSignal = true,
// Base URL configuration
UseGetBaseUrlMethod = true,
BaseUrlTokenName = "API_BASE_URL"
};
var generator = new TypeScriptClientGenerator(document, settings);
string clientCode = generator.GenerateFile();var settings = new TypeScriptClientGeneratorSettings
{
ClassName = "ApiClient",
Template = TypeScriptTemplate.Axios,
PromiseType = PromiseType.Promise,
// Client generation
GenerateClientClasses = true,
GenerateClientInterfaces = true,
GenerateDtoTypes = true,
// HTTP settings
UseAbortSignal = true,
WithCredentials = true,
// Response handling
GenerateResponseClasses = false,
WrapDtoExceptions = true
};
var generator = new TypeScriptClientGenerator(document, settings);
string clientCode = generator.GenerateFile();public enum TypeScriptTemplate
{
JQueryPromises,
JQueryCallbacks,
AngularJS,
Angular,
Knockout,
Fetch,
Aurelia,
JQueryPromisesES6,
JQueryCallbacksES6,
AngularJSES6,
AngularES6,
KnockoutES6,
FetchES6,
AureliaES6,
Axios
}Generated Angular client with dependency injection:
@Injectable({
providedIn: 'root'
})
export class ApiClient {
private http: HttpClient;
private baseUrl: string;
protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined;
constructor(@Inject(HttpClient) http: HttpClient, @Optional() @Inject(API_BASE_URL) baseUrl?: string) {
this.http = http;
this.baseUrl = baseUrl ?? "";
}
getUsers(): Observable<User[]> {
let url_ = this.baseUrl + "/api/users";
return this.http.get<User[]>(url_);
}
}Generated Fetch API client:
export class ApiClient {
private baseUrl: string;
protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined;
constructor(baseUrl?: string) {
this.baseUrl = baseUrl ?? "";
}
async getUsers(): Promise<User[]> {
const url_ = this.baseUrl + "/api/users";
const response = await fetch(url_, {
method: "GET",
headers: {
"Accept": "application/json"
}
});
return response.json();
}
}public class TypeScriptClientTemplateModel : TypeScriptTemplateModelBase
{
public string ModuleName { get; }
public string ClassName { get; }
public bool HasOperations { get; }
public bool HasBaseUrl { get; }
public bool GenerateClientInterface { get; }
public bool IsAngular { get; }
public IEnumerable<TypeScriptOperationModel> Operations { get; }
public string BaseUrl { get; }
public string ConfigurationClass { get; }
}public class TypeScriptOperationModel : OperationModelBase<TypeScriptParameterModel, TypeScriptResponseModel>
{
public string MethodName { get; }
public string HttpMethod { get; }
public string Path { get; }
public string Summary { get; }
public string Description { get; }
public bool IsDeprecated { get; }
public string ResultType { get; }
public bool IsFile { get; }
public IEnumerable<TypeScriptParameterModel> Parameters { get; }
public TypeScriptResponseModel SuccessResponse { get; }
}public class TypeScriptParameterModel : ParameterModelBase
{
public string Name { get; }
public string VariableName { get; }
public string Type { get; }
public string Description { get; }
public bool IsRequired { get; }
public bool IsOptional { get; }
public bool IsNullable { get; }
public OpenApiParameterKind Kind { get; }
public string SerializationMethod { get; }
}Base model for framework-specific features.
public abstract class TypeScriptFrameworkModel
{
public abstract string HttpClientType { get; }
public abstract string RequestUrlType { get; }
public abstract string RequestOptionsType { get; }
public abstract string ResponseType { get; }
public abstract string PromiseType { get; }
}public class TypeScriptFrameworkAngularModel : TypeScriptFrameworkModel
{
public override string HttpClientType => "HttpClient";
public override string RequestUrlType => "string";
public override string RequestOptionsType => "RequestInit";
public override string ResponseType => "HttpResponse<any>";
public override string PromiseType => "Observable";
public bool IsAngular2Plus { get; }
public bool UseRxJS6 { get; }
public string InjectionTokenType { get; }
}public enum PromiseType
{
Promise,
QPromise
}public enum HttpClass
{
Http,
HttpClient
}public enum InjectionTokenType
{
OpaqueToken,
InjectionToken
}var settings = new TypeScriptClientGeneratorSettings
{
ExtensionCode = new TypeScriptExtensionCode
{
ExtensionClasses = new[]
{
"export class CustomExtension { }"
},
ExtensionMethods = new[]
{
"customMethod(): void { console.log('custom'); }"
}
}
};var settings = new TypeScriptClientGeneratorSettings
{
TypeScriptGeneratorSettings = new TypeScriptGeneratorSettings
{
TypeStyle = TypeScriptTypeStyle.Interface,
EnumStyle = TypeScriptEnumStyle.Enum,
NullValue = TypeScriptNullValue.Null,
GenerateConstructorInterface = true,
ConvertConstructorInterfaceData = true
}
};// Generate separate clients for different tags
var settings = new TypeScriptClientGeneratorSettings
{
Template = TypeScriptTemplate.Angular,
OperationNameGenerator = new MultipleClientsFromFirstTagAndOperationIdGenerator(),
GenerateClientInterfaces = true
};
var generator = new TypeScriptClientGenerator(document, settings);
string clientsCode = generator.GenerateFile();var settings = new TypeScriptClientGeneratorSettings
{
ClassName = "ApiService",
Template = TypeScriptTemplate.Axios,
PromiseType = PromiseType.Promise,
GenerateClientClasses = true,
GenerateClientInterfaces = true,
UseAbortSignal = true,
WithCredentials = true
};var settings = new TypeScriptClientGeneratorSettings
{
ClassName = "ApiClient",
Template = TypeScriptTemplate.FetchES6,
PromiseType = PromiseType.Promise,
GenerateClientClasses = true,
GenerateResponseClasses = true,
UseAbortSignal = true,
UseTransformResultMethod = true
};// Generated service registration
@Injectable({
providedIn: 'root'
})
export class ApiClient {
constructor(
@Inject(HttpClient) http: HttpClient,
@Optional() @Inject(API_BASE_URL) baseUrl?: string
) {
// Implementation
}
}
// In app.module.ts
providers: [
{ provide: API_BASE_URL, useValue: 'https://api.example.com' },
ApiClient
]// Custom hook using generated client
import { useEffect, useState } from 'react';
import { ApiClient, User } from './generated/api-client';
const apiClient = new ApiClient('https://api.example.com');
export function useUsers() {
const [users, setUsers] = useState<User[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
apiClient.getUsers()
.then(setUsers)
.finally(() => setLoading(false));
}, []);
return { users, loading };
}