富文本字段获得真实的TypeScript类型
我们非常重视TinaCMS的开发者体验,而TypeScript是其核心。因此,只要我们能给您提供一个合适的类型而不是any,我们就会这样做。
富文本字段一直是个例外。从@tinacms/cli 3.0.0和tinacms 3.14.0开始,它们返回为TinaMarkdownContent,这与<TinaMarkdown>已经期望的类型相同。
注意: 这对于TypeScript用户来说是一个重大变化。针对any编译的代码在升级后可能无法编译。升级下的表格显示了需要更改的内容。
展示代码
在tina/__generated__/types.ts中,帖子查询的类型更改如下:
// 之前export type PostQuery = { post: { title: string, _body: any } };// 之后export type PostQuery = { post: { title: string, _body: TinaMarkdownContent | null } };
使用any时,这两行代码编译正常,但在运行时会崩溃。现在TypeScript会捕捉到它们:
const excerpt = data.post._body?.slice(0, 160);// 属性'slice'在类型'TinaMarkdownContent'上不存在。const count = data.post._body?.childrn.length;// 属性'childrn'在类型'TinaMarkdownContent'上不存在。您是想说'children'吗?
您的编辑器在您输入时也会建议type和children。
如果您在空检查中包装<TinaMarkdown>,您可以去掉它,因为从tinacms 3.14.0开始,它的content属性接受null和undefined:
// 之前{data.post._body && <TinaMarkdown content={data.post._body} />}// 之后<TinaMarkdown content={data.post._body} />
如果您有将富文本作为属性的组件,请将any替换为TinaMarkdownContent以获得相同的检查:
import { TinaMarkdown, type TinaMarkdownContent } from 'tinacms/dist/rich-text';export const Callout = ({ body }: { body: TinaMarkdownContent }) => (<aside className="callout"><TinaMarkdown content={body} /></aside>);
为什么_values仍然是any
GraphQL API中的每个文档也有一个_values字段,它将所有字段作为一个JSON对象返回。我们尝试将其类型化为unknown,但通过它读取文档的项目(如我们的自托管演示)几乎每行都需要一个转换,而转换并不比any更安全。更好的解决方案是为每个集合的_values生成一个类型,我们将在v4发布后研究这一点。
升级
一起更新到tinacms 3.14.0和@tinacms/cli 3.0.0:
pnpm update --latest tinacms @tinacms/cli# 或者npm install tinacms@latest @tinacms/cli@latest
启动您的开发服务器以便CLI重新生成您的类型,然后运行tsc --noEmit以查看TypeScript发现了什么:
如果您的代码 | 更改 |
|---|---|
读取除 | 将它们添加到您自己的类型中,例如 |
将可选的富文本字段传递给 | 无需更改。可选:您可以去掉其周围的任何空检查。 |
有将富文本作为 | 可选:将属性类型化为 |
读取 | 无需更改。 |
有 | 无需更改。您的查询和内容保持不变。 |
如果在升级后富文本字段仍然返回为any,或者TypeScript标记了您认为正常的代码,请打开一个问题或在Discord上找到我们。