📝

astro-typed-links で型安全にリンクを書く

2025/01/07に公開

概要

astro-typed-links は先月 v1.0.0 がリリースされたばかりの比較的新しい Astro Integration で、型安全にリンクを書けるようになる。
Astro の公式ブログ で紹介されていたので使ってみた。

環境

  • astro: 5.1.2
    • astro-typed-links は Astro v5 で追加されたばかりの astro:routes:resolved というフックを用いているため、Astro v5 が必須
  • astro-typed-links: 1.1.1

使ってみた

インストールについては README に従って pnpm astro add astro-typed-links を実行すれば設定ファイルの更新までやってくれる。

インストール後に一度 astro dev を実行すると .astro/integrations/astro-typed-links に型が生成される。

使用方法も README に書いてあるが、2025/01/05 時点で README が最新の仕様に追従していない。
README では "astro-typed-links" から link をインポートしているが、v1.1.1 においては "astro-typed-links/link" からインポートする必要がある。

import { link } from "astro-typed-links/link";

link('/blog/[slug]', { params: { slug: 'foo' }})

link の第一引数に型がついており、下記のように候補を出してくれる。(画像は VSCode での編集時のスクリーンショット)

私は Astro の設定で trailingSlash: "always" を指定しているにも関わらず、自分でリンクを書くときに最後のスラッシュを忘れることがたびたびあるが、astro-typed-links を使うとスラッシュ忘れもきちんとエラーにしてくれる。

パスパラメータは小文字統一するほうがよさそう

使用していて /foo/[id]/[childIndex] というパスの型が上手くつかないことに気づいた。

実装を確認したところ、astro-typed-links は IntegrationResolvedRoute という型のオブジェクトを利用している。
IntegrationResolvedRoutepattern が astro-typed-links の link の第一引数の加工元になるのだが、pattern はすべて小文字になるようだった。
IntegrationResolvedRouteparams は第二引数の加工元で、こちらは大文字をそのままにする。

astro-typed-links v1.1.1 ではこのように大文字・小文字の差異が発生することを考慮しておらず、第一引数と第二引数のキーが完全一致することを前提に実装されている。
よって /foo/[id]/[childIndex] というパスについては

link("/foo/[id]/[childindex]/", { params: { id: "1", childIndex: "2" }})

のように書くことになるのだが、[childindex]params.childIndex に指定した値で置き換えられることがなく、リンクを意図したように設定できなかった。

本件については単純にパスパラメータを小文字に統一しておくのが無難な解決策だと思う。

感想

パスパラメータが大文字を含んでいる場合にうまくいかなかったが、それ以外は私の使用範囲では問題なく使用できた。
公式 Integration ではないが、非公開の仕様を使ったハック的な Integration ではなく、Astro Integration API を使って作られているので壊れにくいのではないかとも思う。

また実装がそれほど複雑ではなかったので、参考にして自分好みの Integration を自作するのもよさそうだと思った。

chot Inc. tech blog

Discussion