typesafe-api-endpoints v1.15.1
typesafe-api-endpoints
This is a proof of concept I have created to see how far we can take TypeScripts type inference to create a fully typesafe endpoints schema.
Result: It works quiet well! (with TypeScript version 4.4.x)
Note: I have used it in a
SvelteKitproduction environment for a few months but recently switched totRPCbecause I currently have no time to maintain this project.
Usage:
- First you need to define a
Schemacontaining all HTTP methods, it's endpoints, slugs, query params and return types. - Then use the
Schemato implement aServer-handler - Call the endpoints from the
Client
Schema
We can define a schema like:
type Schema = CreateTypesafeApiEndpointsSchema<{
GET: {
'products': Product[]
'products?limit': Product[]
'product/{id}': Product
}
POST: {
'product': (product: Product) => boolean
},
PUT: {
'product/{productId}': (product: Partial<Product>) => boolean
}
}>Server
And can use the Schema type for our server-handler that forces us to implement all methods and it's endpoints:
export const handler: ServerHandler<Schema, 'SvelteKit'> = {
GET: {
'products': async () => {
return products
},
'products?limit': async ({ query: { limit = Infinity } }) => {
return products.slice(0, +limit)
},
'product/{id}': async ({ slugs: { id } }) => {
return products.find(({ id: productId }) => +id === productId)
}
},
POST: {
'product': async ({ body: product }) => {
// create logic
return true
}
},
PUT: {
'product/{productId}': async ({ slugs: { productId }, body: product }) => {
// update logic
return true
}
}
}Client
We now can also create the client:
export const api = createTypesafeApiEndpointsClient<Schema>('api-endpoint', fetch)Whenever we use api a request is made to the endpoint we have provided as the first argument (in this case : /api-endpoint)
We can now call all endpoints from the api-object and get fully typed
const loadData = async () => {
const response = await api.GET('product/{id}', { slugs: { id: '123' }, query: undefined })
if (response.error) {
throw response.error
}
return response.data
}
const data = await loadData()
// => 'data' is of type 'Product'I could not get rid of needing to pass also
undefinedin some cases. I think the type definitions are to complex for TypeScript to resolve everything correctly.
Examples
You can take a look ath the examples folder to see an implementation of this library
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago