Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feTS - Enhancing Type Safety in REST API #1297

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vale.ini
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ IgnoredScopes = script, code, tt, pre, figure, blockquote

BasedOnStyles = Vale, write-good, alex, Readability

write-good.E-Prime = NO
write-good.E-Prime = NO
22 changes: 21 additions & 1 deletion .vale/styles/Vocab/Blog/accept.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,24 @@ Todo
Baz
Hasura
fets
createClient
createClient
tuvalSimha
Spotify
topTracks
openapi
OpenAPI
api
API
TuvalSimha
time_range
short_term
async
spotify
feTS
Sportstats
openApi
json
useQuery
isLoading
useState
selectedClub
22 changes: 11 additions & 11 deletions website/blogs.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
[
{
"title": "Empowering REST API Dev with feTS",
"description": "feTS - type safety, efficiency & seamless TypeScript/OpenAPI",
"tags": ["typescript", "openapi", "rest", "api", "feTS"],
"authors": ["tuvalSimha"],
"link": "/blog/type-safe-your-api",
"image": "/blog-assets/type-safe-your-api/banner.png",
"date": "2023-08-14",
"thumbnail": "/blog-assets/type-safe-your-api/banner.png"
},
{
"title": "Hive Summer Update 2023",
"description": "Learn what is new on GraphQL Hive. Learn what is new on GraphQL Hive. Learn what is new on GraphQL Hive.",
"description": "Learn what is new on GraphQL Hive, we have shipped a lot of new exciting features and improvements.",
"tags": ["graphql", "graphql-hive"],
"authors": ["laurin", "kamil", "dimitri", "dotan"],
"link": "/blog/hive-summer-update-2023",
Expand Down Expand Up @@ -208,16 +218,6 @@
"date": "2022-12-06",
"thumbnail": "/blog-assets/graphql-yoga-nest-v9/thumbnail.png"
},
{
"title": "GraphQL File Uploads with S3",
"description": "Learn how to upload and do File Uploads with GraphQL and S3.",
"tags": ["graphql", "best-practices"],
"authors": ["laurin"],
"link": "/blog/graphql-file-uploads-with-s3",
"image": "/blog-assets/x",
"date": "2022-11-17",
"thumbnail": "/blog-assets/x"
},
{
"title": "Announcing GraphQL Yoga v3",
"description": "The new version of GraphQL Yoga is out! Learn what has improved and what is new!",
Expand Down
290 changes: 290 additions & 0 deletions website/pages/blog/type-safe-your-api.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,290 @@
---
title: feTS - Enhancing Type Safety in REST API
authors: tuvalSimha
date: 2023-08-14
tags: [typescript, openapi, rest, api, feTS]
description: feTS - type safety, efficiency & seamless TypeScript/OpenAPI
thumbnail: /blog-assets/type-safe-your-api/banner.png
image: /blog-assets/type-safe-your-api/banner.png
---

## Introduction

About two years ago, I began my journey to become a developer, driven by a strong passion for
learning and creating. As a junior developer, I was eager to find a project that would help me grow
my skills while being fun and interesting.

For my project, I needed to use an REST API, to be specific. This API allows me to fetch data from a
server and use it in my application. It supports operations like reading (GET), updating (PUT),
creating (POST), and deleting (DELETE) various types of data.

Working with REST APIs can be tricky due to issues like the lack of type safety, which can lead to
errors and bugs during development. In this blog post, I'll introduce you to `feTS`, a solution that
simplifies REST API development. `feTS` help with these challenges, making API development more
reliable and straight forward.

## Introducing `feTS`: Type-Safe REST API Development

`feTS`, which stands for 'Fetch' and 'TypeScript,' is a modern technology that enhances REST APIs.
By using TypeScript and the OpenAPI specification, feTS ensures that data exchanged between the
client and server is clearly defined and error-free. This proactive approach identifies and prevents

Check failure on line 30 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L30

[alex.Condescending] Using 'clearly' may come across as condescending.
Raw output
{"message": "[alex.Condescending] Using 'clearly' may come across as condescending.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 30, "column": 22}}}, "severity": "ERROR"}

Check warning on line 30 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L30

[write-good.Weasel] 'clearly' is a weasel word!
Raw output
{"message": "[write-good.Weasel] 'clearly' is a weasel word!", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 30, "column": 22}}}, "severity": "WARNING"}
errors during development, making your applications more dependable and robust.

## A Practical Example: Leveraging `feTS` for Soccer Team Information

To illustrate the power of `feTS`, let's dive into a real-world example. We'll build a demo app that

Check warning on line 35 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L35

[alex.ProfanityUnlikely] Be careful with 'dive', it’s profane in some cases.
Raw output
{"message": "[alex.ProfanityUnlikely] Be careful with 'dive', it’s profane in some cases.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 35, "column": 42}}}, "severity": "WARNING"}
interacts with the
[SportStats](https://sportsdata.io/developers/api-documentation/soccer#/sports-data-feeds) V4 API

Check failure on line 37 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L37

[Vale.Terms] Use 'Sportstats' instead of 'SportStats'.
Raw output
{"message": "[Vale.Terms] Use 'Sportstats' instead of 'SportStats'.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 37, "column": 2}}}, "severity": "ERROR"}
using `feTS`. Our goal is to fetch soccer team information and display it in an intuitive user
interface.

### Step 1: Obtain a Free Trial Token for Sportstats

Check warning on line 41 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L41

[write-good.TooWordy] 'Obtain' is too wordy.
Raw output
{"message": "[write-good.TooWordy] 'Obtain' is too wordy.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 41, "column": 13}}}, "severity": "WARNING"}

To get started, create a free trial Token for SportStats API access. The registration process is

Check failure on line 43 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L43

[Vale.Terms] Use 'Sportstats' instead of 'SportStats'.
Raw output
{"message": "[Vale.Terms] Use 'Sportstats' instead of 'SportStats'.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 43, "column": 47}}}, "severity": "ERROR"}
straight forward and won't take much time. You can find the registration form
[here](https://sportsdata.io/cart/free-trial).

By the way, you can choose any other API you want, but for this example, we will use the SportStats

Check failure on line 47 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L47

[Vale.Terms] Use 'Sportstats' instead of 'SportStats'.
Raw output
{"message": "[Vale.Terms] Use 'Sportstats' instead of 'SportStats'.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 47, "column": 90}}}, "severity": "ERROR"}
API. You can find openApi at `APIS.GURU` [website](https://apis.guru/about/)

### Step 2: Incorporate OpenAPI Definitions into TypeScript

To integrate OpenAPI definitions into a TypeScript file and export them using the `as const`
modifier. This process ensures strong typing and easy integration with `feTS`. A sample code snippet
is provided below:

Check warning on line 54 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L54

[write-good.Passive] 'is provided' may be passive voice. Use active voice if you can.
Raw output
{"message": "[write-good.Passive] 'is provided' may be passive voice. Use active voice if you can.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 54, "column": 1}}}, "severity": "WARNING"}

```typescript filename="openapi.ts"
export default { openapi: '3.0.0' /* ... */ } as const
```

`openapi.ts` GitHub file
[here](https://github.com/TuvalSimha/feTS-example/blob/main/src/fets/openapi.ts). You can choose any
OpenAPI file you want, but for this example, we will use the SportStats OpenAPI file. You can find

Check failure on line 62 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L62

[Vale.Terms] Use 'Sportstats' instead of 'SportStats'.
Raw output
{"message": "[Vale.Terms] Use 'Sportstats' instead of 'SportStats'.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 62, "column": 62}}}, "severity": "ERROR"}
the OpenAPI file [here](https://sportsdata.io/developers/sports-data-open-api-swagger-files).

### Step 3: Install `feTS` and Create a Client

Now, we are ready to install `feTS` and create a new client. To do this, you can visit the docs
[here](https://the-guild.dev/openapi/fets/client/quick-start#installation).

Next, create a new `TypeScript` file and import the `createClient` function from the `feTS` package.
Then, use the `createClient` function to instantiate a new client.

```typescript filename="client.ts"
import { createClient, type NormalizeOAS } from 'feTS'
import type openapi from './openapi'

export const client = createClient<NormalizeOAS<typeof openapi>>({
endpoint: 'https://api.sportsdata.io/v4/soccer/stats'
})
```

`client.ts` GitHub file
[here](https://github.com/TuvalSimha/feTS-example/blob/main/src/fets/client.ts).

In the code below, we demonstrate how to set up the `feTS` client with a custom error handling

Check warning on line 85 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L85

[write-good.TooWordy] 'demonstrate' is too wordy.
Raw output
{"message": "[write-good.TooWordy] 'demonstrate' is too wordy.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 85, "column": 23}}}, "severity": "WARNING"}
plugin. This plugin is added to enhance the error handling capabilities of the client. This

Check warning on line 86 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L86

[write-good.Passive] 'is added' may be passive voice. Use active voice if you can.
Raw output
{"message": "[write-good.Passive] 'is added' may be passive voice. Use active voice if you can.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 86, "column": 21}}}, "severity": "WARNING"}
error-handling plugin is to provide a robust mechanism for handling HTTP errors that may occur
during API requests. When the server responds with an error status code, this plugin ensures that an
informative error message is thrown, including the status code, status text, and the URL that

Check warning on line 89 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L89

[write-good.Passive] 'is thrown' may be passive voice. Use active voice if you can.
Raw output
{"message": "[write-good.Passive] 'is thrown' may be passive voice. Use active voice if you can.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 89, "column": 27}}}, "severity": "WARNING"}

Check failure on line 89 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L89

[Vale.Terms] Use 'url' instead of 'URL'.
Raw output
{"message": "[Vale.Terms] Use 'url' instead of 'URL'.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 89, "column": 86}}}, "severity": "ERROR"}
triggered the error.

```typescript filename="client.ts"
/* eslint-disable react-hooks/rules-of-hooks */
import { ClientPlugin, createClient, type NormalizeOAS } from 'feTS'
import type openapi from './openapi'

function useErrorHandler(): ClientPlugin {
return {
onResponse({ response }) {
if (!response.ok) {
throw new Error(
`Request failed with status ${response.status}, ${response.statusText}, ${response.url}`

Check warning on line 102 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L102

[alex.ProfanityUnlikely] Be careful with 'failed', it’s profane in some cases.
Raw output
{"message": "[alex.ProfanityUnlikely] Be careful with 'failed', it’s profane in some cases.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 102, "column": 20}}}, "severity": "WARNING"}
)
}
}
}
}

export const client = createClient<NormalizeOAS<typeof openapi>>({
plugins: [useErrorHandler()],
endpoint: 'https://api.sportsdata.io/v4/soccer/stats'
})
```

By using the custom plugins, you can add your own logic to the client. You can find more information
about plugins [here](https://the-guild.dev/openapi/fets/client/plugins).

### Step 4: Use the Client to Fetch Data from the API

Now, let's use our client to get data from the API. We'll use the `feTS` client we made earlier to
fetch information from the SportStats API. The fetchAllClubs function will show how `feTS` makes it

Check failure on line 121 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L121

[Vale.Terms] Use 'Sportstats' instead of 'SportStats'.
Raw output
{"message": "[Vale.Terms] Use 'Sportstats' instead of 'SportStats'.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 121, "column": 28}}}, "severity": "ERROR"}
easy to request data from the API and deal with the results.

```typescript filename="endpoint.ts"
export async function fetchAllClubs() {
const response = await client['/{format}/Teams/{competition}'].get({
params: {
competition: 'EPL',
format: 'json'
},
headers: {
'Ocp-Apim-Subscription-Key': YOUR_TOKEN_HERE
},
query: {
key: YOUR_TOKEN_HERE
}
})

const data = await response.json()

return data
}
```

In this code snippet, we bring in the client object we made using `feTS`. The `fetchAllClubs`
function shows how to use this client to send a `GET` request to the SportStats API's

Check failure on line 146 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L146

[Vale.Terms] Use 'Sportstats' instead of 'SportStats'.
Raw output
{"message": "[Vale.Terms] Use 'Sportstats' instead of 'SportStats'.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 146, "column": 70}}}, "severity": "ERROR"}
`/Teams/{competition}` endpoint. We provide the needed details like the competition and format as
well as the required authentication headers. Your IDE should automatically fill in these parameters
for you.

![Endpoint auto complete](/blog-assets/type-safe-your-api/endpoint.png)

![Headers auto complete](/blog-assets/type-safe-your-api/autocomplate.png)

### Step 5: Use the Data from the API

In this step, we'll demonstrate how to use the data fetched from the SportStats API using the

Check warning on line 157 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L157

[write-good.TooWordy] 'demonstrate' is too wordy.
Raw output
{"message": "[write-good.TooWordy] 'demonstrate' is too wordy.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 157, "column": 21}}}, "severity": "WARNING"}

Check failure on line 157 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L157

[Vale.Terms] Use 'Sportstats' instead of 'SportStats'.
Raw output
{"message": "[Vale.Terms] Use 'Sportstats' instead of 'SportStats'.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 157, "column": 70}}}, "severity": "ERROR"}
`fetchAllClubs` function. We'll utilize the `useQuery` hook from the `react-query` library to

Check warning on line 158 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L158

[write-good.TooWordy] 'utilize' is too wordy.
Raw output
{"message": "[write-good.TooWordy] 'utilize' is too wordy.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 158, "column": 33}}}, "severity": "WARNING"}

Check warning on line 158 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L158

[alex.ProfanityUnlikely] Be careful with 'hook', it’s profane in some cases.
Raw output
{"message": "[alex.ProfanityUnlikely] Be careful with 'hook', it’s profane in some cases.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 158, "column": 56}}}, "severity": "WARNING"}
efficiently manage data fetching and rendering in our React application.

The `useQuery` hook from the react-query library provides a convenient way to fetch and manage

Check warning on line 161 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L161

[alex.ProfanityUnlikely] Be careful with 'hook', it’s profane in some cases.
Raw output
{"message": "[alex.ProfanityUnlikely] Be careful with 'hook', it’s profane in some cases.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 161, "column": 16}}}, "severity": "WARNING"}
asynchronous data in a React component. It abstracts away the complex logic of data fetching,
caching, and error handling.

Here's an example of how you can use `useQuery` to fetch and display data from the SportStats API in

Check failure on line 165 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L165

[Vale.Terms] Use 'Sportstats' instead of 'SportStats'.
Raw output
{"message": "[Vale.Terms] Use 'Sportstats' instead of 'SportStats'.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 165, "column": 84}}}, "severity": "ERROR"}
your `App.tsx` component:

```typescript filename="App.tsx"
import { useQuery } from 'react-query'
import { fetchAllClubs } from './feTS/endpoint'

function App() {
const { data, isLoading, error } = useQuery('clubs', fetchAllClubs)

if (isLoading) {
return <div>Loading...</div>
}

if (error) {
return <div>Error: {error.message}</div>
}

return (
<div>
{data?.map(club => (
<div key={club.TeamId}>{club.Name}</div>
))}
</div>
)
}

export default App
```

For more advanced and design example, you can check out the
[example](https://github.com/TuvalSimha/feTS-example/blob/main/src/App.tsx) in the GitHub
repository.

Lets create a design example for our soccer teams data:

```typescript filename="App.tsx"
import { useState } from 'react'
import { useQuery } from 'react-query'
import { TeamsCards } from './components/teams-crads'
import { fetchAllClubs } from './feTS/endpoint'
import { Club } from './feTS/type-helpers'

export function App() {
const [selectedClub, setSelectedClub] = useState<Club | undefined>(undefined)

const { data, isLoading, error } = useQuery('clubs', fetchAllClubs)

if (isLoading) {
return <div>Loading...</div>
}

if (error) {
return <div>Error: {error.message}</div>
}

return (
<div>
<TeamsCards clubData={data} setSelectedClub={setSelectedClub} />
</div>
)
}
```

In this code snippet, i created a custom component called `TeamsCards` (GitHub file
link)[https://github.com/TuvalSimha/feTS-example/blob/main/src/components/teams-crads.tsx] that
renders a list of cards with the club's name and logo. When the user clicks on a card, the
`setSelectedClub` function is called with the selected club as an argument. This allows us to

Check warning on line 232 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L232

[write-good.Passive] 'is called' may be passive voice. Use active voice if you can.
Raw output
{"message": "[write-good.Passive] 'is called' may be passive voice. Use active voice if you can.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 232, "column": 28}}}, "severity": "WARNING"}
display the selected club's information in a separate component.

In your code snippet, you've leveraged the power of `feTS` to define the Club type, which represents
a structured and strongly-typed representation of the data schema for a soccer club. This type is
essential for maintaining type safety and ensuring that the data exchanged between your application
and the API is well-defined and consistent.

The `Club` type is inferred using `feTS` `OASModel` type.This type inference mechanism allows you to

Check warning on line 240 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L240

[write-good.Passive] 'is inferred' may be passive voice. Use active voice if you can.
Raw output
{"message": "[write-good.Passive] 'is inferred' may be passive voice. Use active voice if you can.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 240, "column": 17}}}, "severity": "WARNING"}

Check failure on line 240 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L240

[Vale.Spelling] Did you really mean 'OASModel'?
Raw output
{"message": "[Vale.Spelling] Did you really mean 'OASModel'?", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 240, "column": 43}}}, "severity": "ERROR"}
generate TypeScript types directly from the OpenAPI schema defined in your `openapi` file. Here's
how you've done it:

```typescript filename="type-helpers.ts"
import { NormalizeOAS, OASModel } from 'feTS'
import openapi from './openapi'

export type Club = OASModel<NormalizeOAS<typeof openapi>, 'Team'>
```

GitHub file [here](https://github.com/TuvalSimha/feTS-example/blob/main/src/fets/type-helpers.ts).

![Club type](/blog-assets/type-safe-your-api/type.png)

And its done! You've successfully created a React application that fetches data from the SportStats

Check warning on line 255 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L255

[write-good.Weasel] 'successfully' is a weasel word!
Raw output
{"message": "[write-good.Weasel] 'successfully' is a weasel word!", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 255, "column": 22}}}, "severity": "WARNING"}

Check failure on line 255 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L255

[Vale.Terms] Use 'Sportstats' instead of 'SportStats'.
Raw output
{"message": "[Vale.Terms] Use 'Sportstats' instead of 'SportStats'.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 255, "column": 90}}}, "severity": "ERROR"}
API using `feTS`.

![Result](/blog-assets/type-safe-your-api/result.gif) The full code for this example is available on
[GitHub](https://github.com/TuvalSimha/feTS-example)

## Leveraging `feTS` for Enhanced API Development

In this blog post, we've explored the transformative capabilities of `feTS` for REST API

Check failure on line 263 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L263

[Vale.Spelling] Did you really mean 'transformative'?
Raw output
{"message": "[Vale.Spelling] Did you really mean 'transformative'?", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 263, "column": 39}}}, "severity": "ERROR"}
development. By combining TypeScript's type safety and OpenAPI's structured definitions, `feTS`
empowers developers to build efficient, reliable, and well-structured applications. To recap, `feTS`
offers the following benefits:

- Enhanced Type Safety: `feTS` provides robust type safety, catching potential issues at compile
time and reducing runtime errors.
- Improved Efficiency: With auto-generated API clients and TypeScript types, `feTS` eliminates
manual response parsing and improves overall development efficiency.

Check warning on line 271 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L271

[write-good.TooWordy] 'overall' is too wordy.
Raw output
{"message": "[write-good.TooWordy] 'overall' is too wordy.", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 271, "column": 40}}}, "severity": "WARNING"}
- Unified Interface: `feTS`'s unified and structured endpoint interface simplifies API navigation
and promotes collaboration among developers.
- Seamless Development: The `feTS` workflow seamlessly integrates with development processes, from
API interactions to UI rendering.

## Embracing a Future of Seamless REST API Development

As you integrate `feTS` into your projects, consider exploring its full potential. Experiment with
custom plugins, delve into advanced use cases, and stay engaged with the `feTS` community to
contribute to its evolution.

In closing, `feTS` represents a beacon of innovation in the dynamic world of software development.
By adopting `feTS`, you're not only enhancing your REST API development process; you're embracing a

Check warning on line 284 in website/pages/blog/type-safe-your-api.mdx

View workflow job for this annotation

GitHub Actions / vale

[vale] website/pages/blog/type-safe-your-api.mdx#L284

[write-good.Weasel] 'only' is a weasel word!
Raw output
{"message": "[write-good.Weasel] 'only' is a weasel word!", "location": {"path": "website/pages/blog/type-safe-your-api.mdx", "range": {"start": {"line": 284, "column": 32}}}, "severity": "WARNING"}
culture of continuous improvement and excellence. Whether you're building a personal project or a
large-scale application, `feTS` equips you with the tools to create exceptional, type-safe, and
efficient software.

Thank you for joining us on this journey through [feTS](https://the-guild.dev/openapi/fets). Here's
to a future filled with seamless and elevated REST API development!
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading