A Guide to OpenAPI Code Generation for TypeScript
In this article article I explain how to automatically generate the client code for a REST API.
The basic idea is to specify the API in a format called OpenAPI, and then feed that specification into a tool called OpenAPI Generator. The target language in this article is TypeScript.
Why would would somebody generate code for a REST API?
- Writing client side code for a REST API is tedious, repetitive, and error prone. Generating the code automatically solves these issues.
- With TypeScript, it is even more desirable to generate this code, because it means that requests and responses are fully typed, including your deeply structured domain objects. There is no need to tolerate the
any
type. - Because the approach is based on a shared API specification, client and server are more likely to stay compatible.
My experience with this approach is in fact very good.
What is OpenAPI?
OpenAPI is a format for specifying REST APIs. It is also called "Swagger specification". The format is documented here:
https://swagger.io/specification/
With OpnAPI, the API is specified in a machine readable format based on YAML or JSON. This specification can then be used to generate documention, code, or can be used at runtime to verify requests and responses.
What is OpenAPI Generator?
The people behind the OpenAPI standard make a code generator called Swagger generator. This code generator seems to have lost the community's attention to a fork from Swagger generator called OpenAPI Generator. It can generate code for both clients and servers, and for many languages and platforms.
Example languages on the client side are:
- JavaScript
- TypeScript
- Kotlin
- Swift
Example languages on the server side are:
- Java
- Kotlin
- Go
OpenAPI has two major version in active use, OAS 3 and OAS 2 (which was called Swagger). Both are supported by OpenAPI Generator.
The website with documentation lives at https://openapi-generator.tech.
Our Example API
As a good example of a REST API, I will use "JSON Placeholder" from https://jsonplaceholder.typicode.com. This site offer a basic REST API for experimentation that can be accessed by anybody.
For our code generator to work, we will need a specification file. Valid file formats are JSON and YAML. For this article, I have written an OpenAPI specification for JSON Placeholder's API in a file called json-placeholder-api.yaml
. You can download it from GitHub: https://github.com/stefanwille/openapi-generator-typescript-example/blob/master/json-placeholder-api.yaml
The API specification is part of an example repo that shows everything I do in this article in a cohesive setup: https://github.com/stefanwille/openapi-generator-typescript-example
Installing OpenAPI Generator
OpenAPI Generator is a Java program, but it can be installed via an npm package called @openapitools/openapi-generator-cli
. Use this command to get the npm:
npm install @openapitools/openapi-generator-cli
After installing the npm, you should run its binary without parameters.
openapi-generator-cli
When you run the npm binary for first time, it will select a stable version of the Java program and download it.
The npm will put the Java program's version number in a new file called openapitools.json
. You should add this file to your version control.
Running the Code Generator
Once I haved installed the npm and generated the configuration file openapitools.json
, I can generate code. The command I use is this:
openapi-generator-cli generate \
-i ./json-placeholder-api.yaml \
-o src/generated-sources/openapi \
-g typescript-fetch \
--additional-properties=supportsES6=true,npmVersion=6.9.0,typescriptThreePlus=true
The command uses the following options:
-i
to specify the specification file-o
to specify the output directory-g
to select the desired output format (TypeScript andfetch()
)--additional-properties
to select some options specific to the selected output format.
The generated code is placed in the directory src/generated-sources/openapi
.
I like to add a script to my package.json
file's scripts
section that allows me to run the code generator from npm via npm run codegen
. The script I use is this:
"codegen": "rm -rf src/generated-sources/openapi; openapi-generator-cli generate -i ./json-placeholder-api.yaml -o src/generated-sources/openapi -g typescript-fetch --additional-properties=supportsES6=true,npmVersion=6.9.0,typescriptThreePlus=true"
It first deletes any generated code and then runs OpenAPI generator.
Using the Generated Code
To use the generated code, I have to set up a Configuration
object. Because I am building a web application in this example, I send all requests to my origin server:
import { Configuration, Post, PostsApi } from "./generated-sources/openapi";
const configuration = new Configuration({
basePath: window.location.origin,
});
Then I can make a PostsApi
object:
const postsApi = new PostsApi(configuration);
On this object I can call individual methods that make requests to the REST api. For example:
const posts: Promise<Post[]> = postsApi.getPosts();
This code looks clean and the returned data is statically typed as Post[]
. If you inspect the generated code for Post
, you find that the specification was translated into a fully typed interface:
export interface Post {
id: number;
userId: number;
title: string;
completed: string;
}
Please check the example repo for more details.
I suggest that you add the generated code to your git repo. Then your colleagues will not have to run the generator for themselves.
Example Code on GitHub
The code is available here on GitHub.