onTheInternet
onTheInternet

Reputation: 7253

Is this approach to fix a typing error between typescript and Contentful's content delivery API safe?

I'm using Astro and Contentful to make a blog. I have a content type called author which has 3 fields.

Name Field Type
Full Name Short text
Headshot Media
Bio Rich Text

I'm working on creating a component that will list out all the authors. My code looks as follows:

---
import { contentfulClient } from "../lib/contentful";
import { documentToHtmlString } from "@contentful/rich-text-html-renderer";
import type { Asset, EntryFieldTypes } from "contentful";


interface Author {
    contentTypeId: "author",
    fields: {
        fullName: EntryFieldTypes.Text,
        headshot: EntryFieldTypes.AssetLink,
        bio: EntryFieldTypes.RichText
    }
}

const authors = await contentfulClient.getEntries<Author>({
    content_type: "author"
})

---
<h1>Authors</h1>
{
    authors.items.map((author) => (
        <p>{author.fields.fullName}</p>
        <img src={`https:${(author.fields.headshot as any).fields.file.url}`} alt="" srcset="">
    ))
}

This works but I had to cast author.fields.headshot as any because typescript was complaining that fields wasn't a property of headshot. And my intellisense could only find sys as a property of headshot.

So this:

<img src={`https:${author.fields.headshot.fields.file.url}`} class="w-full max-w-48" alt="" srcset="">

Does work locally. But when I go to deploy to Netlify the build fails since typescript won't compile. My solution works but it feels dangerous. I thought maybe I was using the wrong EntryFieldTypes property in my Author interface but AssetLink seems to be the most appropriate.

Upvotes: 2

Views: 1545

Answers (2)

mb21
mb21

Reputation: 39227

The Contentful TypeScript definitions are really quite something. Smells heavily like they had to tack them on a dynamic js lib after the fact.

I had a look at their tutorial which mentions EntryFieldTypes.Asset, which doesn't exist. But the closest I got is:

import { type Asset, type EntryFieldTypes } from 'contentful'

const headshot: Asset;

(author.fields.headshot as Asset).fields.file?.url

Note the as Asset is still needed, because the Entry type for some reason sets the type of the field headshot to never. (The author variable is not of type Author but of type Entry<Author, undefined, string>.)

Finally, you could try generating the types automatically.

Upvotes: 4

Robban
Robban

Reputation: 6802

I believe your headshot field should be of type Asset not AssetLink which is a link within a rich text structure.

headshot: Asset,

Upvotes: 0

Related Questions