What if the Post
schema contains a transformation? Let's try this out!
A common transformation is applying a brand to a type using Schema.brand
. We can do this for id
inside Post
:
export class Post extends Schema.Class<Post>("Post")({
userId: Schema.Number,
id: Schema.Number.pipe(Schema.brand("Id")),
title: Schema.String,
body: Schema.String,
}) {
static readonly Array = Schema.Array(this);
}
We are now getting a type error inside index.tsx
:
Type 'number' is not assignable to type 'Brand<"Id">'
By using Schema.encode
the original Post
type lost the brand applied to id
, whereas the posts
prop type inside Posts
is still defined as readonly Post[]
.
This was not an issue before because the encoded and decoded types were the same (no transformation). However, adding a brand makes the decoded type different from the encoded type.
Therefore, to fix the issue we need to accept the encoded schema as a prop. We can do this by accessing the Posts.Encoded
type:
export default function Posts({
posts,
}: {
posts: readonly (typeof Post.Encoded)[];
}) {
return (
<div>
{posts.map((post) => (
<div key={post.id}>
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
))}
</div>
);
}
Every
Schema
exports two types:
Schema.Type
: the decoded type of the schema (after transformations)Schema.Encoded
: the encoded type of the schema (before transformations)With
Schema.Class
the class type (Post
) represents the decoded type (typeof Post.Type
).
With this the type error is gone, and the app is working correctly again.