Use autogenerated Typescript type definitions from your api inside a namespace
This is a follow up on the article “Auto generate TypeScript d.ts from your API requests/responses”, written more than a year ago. Since time changes, so do their setups. There where two things I didn’t like about my previous setup:
- i still had to import types everywhere in my mono-repo, instead of just consuming them, although the title of the previous article promised it (d.ts) … which made no sense :)
- the library used
dtsgenerator
to generate types didn’t support `common path parameters` in open-api spec since they added open-api in a later stage. This i only found out when our api’s where refactored.
So here is the continuation of a new setup to fix both issues. Using a new library which supports both swagger inputs as open-api spec (v2 and v3) and by creating real internal types packages.
Let’s again assume we have a pet-store to make our example easy since the api and it’s specification can be found here: https://petstore3.swagger.io/
Finding pets and adding pets, it’s all in the documentation. Now look for the https://petstore3.swagger.io/api/v3/openapi.json.
Since im assuming you read the first article i now start with having the types setup created, the actual creation will be still explained after this chapter.
Internal Types packages
The first thing we need to be able to create is a `namespace` based on the domain and endpoints, so we can provide it to other parts in our (mono)repo. Then that namespace could be consumed in our app without importing it!. This is still all simple TypeScript.
In tsconfig compilerOptions
we have the typeRoots
option, which can just point to any folder(s) which then assumes it can find packages with type definitions.
The file structure of our repository is:
├── packages
│ ├── components
│ ├── ... etc ...
│ └── types
│ └── animals
│ ├── package.json
│ ├── index.d.ts
│ ├── pet-store.d.ts
│ └── wild-cats.d.ts
└── tsconfig.js
Then the typeRoots
in the main tsconfig.js points to:
"typeRoots": ["./packages/types"],
This setup gives us room to create any types package for the future. Lets create a package.json for our animals:
Now the typings point to an `index.d.ts`, so inside we can have multiple modules and their types. Our start would look like:
This setup makes it possible to use the raw types without the need to import these inside components/services/mocks/etc. So problem 1 is solved, lets continue.
Create types from swagger or open-api endpoints
Now we know how we want our structure all we need is a tool to create typescript types. The tool im using is openapi-typescript since it supported all my requirements: full open-api support, swagger support.
I will wrap the output of the tool inside a namespace. So the petstore endpoint will result in the following type definition:
I hope you scrolled overhere :) So what we now have is a namespace PetStoreRaw
file which is placed as reference inside our types/animals package.
So now anywhere in our application we can use typings without importing them. For example a fetch can now be typed like:
PetStoreRaw['paths']['/pet/findByStatus']['get']['responses']['200']['content']['application/json']
While the result can be passed/used in any component by its schema:
PetStoreRaw['components']["schemas"]["Pet"]
The pet definition is still the same as in my first article