When making a request with HttpClient
we can also validate the response schema using @effect/schema
.
In a separate schema.ts
file we define the schema for a post using Schema.Class
:
src/services/schema.ts
import { Schema } from "@effect/schema";
export class Post extends Schema.Class<Post>("Post")({
userId: Schema.Number,
id: Schema.Number,
title: Schema.String,
body: Schema.String,
}) {}
The schema is based on the response from the jsonplaceholder API:
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}
Since getPosts
returns an array of posts, it's convenient to define a schema for an array of posts directly inside the Post
class:
export class Post extends Schema.Class<Post>("Post")({
userId: Schema.Number,
id: Schema.Number,
title: Schema.String,
body: Schema.String,
}) {
static readonly Array = Schema.Array(this);
}
We then validate the response type using HttpClientResponse.schemaBodyJson
:
- Access the response body using
Effect.flatMap
- Apply the schema to validate the response with
HttpClientResponse.schemaBodyJson
src/services/Api.ts
const make = Effect.gen(function* () {
const baseClient = yield* HttpClient.HttpClient;
const client = baseClient.pipe(
HttpClient.mapRequest(
flow(
HttpClientRequest.prependUrl("https://jsonplaceholder.typicode.com"),
HttpClientRequest.acceptJson
)
)
);
return {
getPosts: client
.get("/posts")
.pipe(
Effect.flatMap(HttpClientResponse.schemaBodyJson(Post.Array)),
Effect.scoped
),
getPostById: (id: string) =>
client
.get(`/posts/${id}`)
.pipe(
Effect.flatMap(HttpClientResponse.schemaBodyJson(Post)),
Effect.scoped
),
} as const;
});
With this both the getPosts
and getPostById
methods are now type-safe:
getPosts
returnsEffect<readonly Post[], HttpClientError | ParseError>
getPostById
returnsEffect<Post, HttpClientError | ParseError>
ParseError
is the error added byschemaBodyJson
when the response doesn't match the schema.