← ホームに戻る

Content Collectionsのスキーマ、TypeScriptの型としても使い回せることに気づいた話

中央のスキーマ設計図から3つの型カードへ同じ構造がつながり、欠けた画像項目のピースをりょんた・おこめ・めいが確認するドット絵

// 記事のポイント

  • Zodスキーマで定義した形を、TypeScriptの型としてコンポーネント側で手書きし直すと、更新のたびにズレるリスクがある
  • 実際に、手書きの型がスキーマの最新の形と食い違っているのを見つけた
  • CollectionEntry<'コレクション名'>['data']から型を直接取り出せば、二重管理をなくせる
りょんた
前にContent Collectionsの基本を紹介したと思うんだけど、実はあの後、地味だけど大事な型のズレを見つけて直したんだよね。今日はその話をしていくよ〜。
おこめ
型のズレ? こめの中では、クッキーの型からはみ出ちゃった生地みたいなイメージなんだけど、合ってる?

同じ形を何度も手書きしていた

このブログの記事データは、`src/content.config.ts`のZodスキーマで形が決まっている。会話のセリフ1つひとつには、話者やテキストのほかに、任意で画像や商品リンクを付けられるようになっており、リンクの中にはショップごとのボタンを並べる`shops`のような配列も入っている。この構造をTypeScriptの型としてコンポーネント側でも使いたい場面が何度も出てきた。
めい
同じ形をあちこちに書き写すの、わりと手間だし、うっかりズレちゃいそうだね〜。
りょんた
そうなんだよね。最初の頃は、記事を表示するコンポーネントごとに`interface Turn`みたいな型を自分で書いてたよ。似たような形の型が、3か所くらいに別々に存在してた。
おこめ
手で何回も書き写してたら、そのうち1個くらい書き忘れちゃうこともあるんじゃない?

実際に見つかったズレ

実際にあった。記事の会話に添える`link`には、商品画像のURLを入れる`image`という項目がスキーマ側に存在していたが、あるコンポーネントの手書きの型にはこの項目が抜けていた。スキーマとは無関係に書かれた型だったため、TypeScript自体はこのズレを教えてくれない。見た目には出ないまま埋まっていたズレだった。
めい
それって、実際の記事の表示に影響が出てたってこと…?
りょんた
そこまでではないよ、たまたま、その項目を使う記事がまだ無かっただけ。でも、これから使おうとしたタイミングで気づかずにハマってた可能性はあったよね。 関連するコードを触ってたときに見つけたんだけど、ちょっとヒヤッとしたよ。

スキーマから型を直接取り出す

直し方は単純で、手書きの型をやめて、スキーマから型そのものを取り出す形にした。`CollectionEntry<'blog'>['data']['conversation'][number]`と書くと、記事データの会話1ターン分の型がそのまま手に入る。画像やリンクのように任意項目になっている部分は、`NonNullable<...>`で「値が入っている場合の形」だけを取り出せる。
おこめ
それって、スキーマさえ合ってれば、こめたちが写し間違えることはもう起きないってこと?
めい
手書きの型自体をなくしちゃえば、そもそも書き間違えようがないもんね〜。
りょんた
そういうこと! スキーマは実行時のチェックだけじゃなくて、TypeScriptの型の元にもできる、っていうのが今回の一番の学びだったかな。同じ形をあちこちで手書きしてる心当たりがあったら、一度スキーマから取り出せないか見直してみるといいかも。

// 記事のまとめ

  • スキーマは実行時のチェックだけでなく、TypeScriptの型の元にもできる
  • 同じ形を複数箇所で手書きしている心当たりがあれば、一度スキーマから型を取り出せないか見直す価値がある

// こめこめハウスの仲間たち

管理人

パパ
りょんた
マーケティング領域を中心に、データ分析・データサイエンスに携わっています。趣味は愛犬遊び、ポイ活、ガジェットなど。
プロフィールを見る →Xでフォローする →

うちの子たち

マルプー
おこめ
小さくて甘えん坊な女の子。自分が一番可愛いと思っている。お散歩じゃなくてパトロールなんだからね!
Instagramでフォローする →
シュナウザー
めい
おこめの姉貴分。大人しい性格の為、いつもおこめに付きまとわれている。優しい人が好きなの。
Instagramでフォローする →