🤕

SvelteKitのダイナミックルーティングで型を指定する無駄話

2024/03/21に公開

SvelteKit(に限った話ではないが)では、ディレクトリ名を[id]のようにすることで動的なURLを作ることができる。

試してみたところ「idの型がない」とVS Codeに指摘されたので、型を指定してみた。

プロジェクトフォルダを作成する

適当に「sveltekit-test」をつくって試す。

/sveltekit-test
npm create svelte@latest .

質問に答える。

┌  Welcome to SvelteKit!
│
◇  Where should we create your project?
│    (hit Enter to use current directory)
│
◇  Which Svelte app template?
│  Skeleton project
│
◇  Add type checking with TypeScript?
│  Yes, using TypeScript syntax
│
◇  Select additional options (use arrow keys/space bar)
│  none
│
└  Your project is ready!

インストール。

/sveltekit-test
npm install

ダイナミックルーティングを実装する

動的URLを想定したページをつくる。

/sveltekit-test/src/routes/sample/[id]/+page.svelte
<script lang="ts">
  // ここはなんでconstじゃないんだろう?
  export let data;
</script>

<p>
  idは{data.params.id}です。
</p>

データハンドリング用のファイルをつくる。

/sveltekit-test/src/routes/sample/[id]/+page.server.ts
export async function load({ params }) {
  console.log(params.id);

  return {
    params
  };
}

この時、load({ params })部分で「モジュール './$types.js' またはそれに対応する型宣言が見つかりません。」という警告が出る。

冒頭にも書いたとおり、本来はnpm run dev状態で上記ファイルを作成するか、この時点でnpm run devすれば良い。警告にもそのようなことが書いてある。

this likely means that SvelteKit's type generation didn't run yet - try running it by executing 'npm run dev' or 'npm run build'

が、ここでは警告内容を斜め読みした結果「paramsに型を指定すればよいのかな」と考え、自分で型を指定してみる。

/sveltekit-test/src/routes/sample/[id]/+page.server.ts
import type { PageServerLoad } from './$types.js';

export async function load({ params }: { params: PageServerLoad }) {
  console.log(params.id);

  return {
    params
  };
}

すると、今度は$types.jsが「モジュール './$types.js' またはそれに対応する型宣言が見つかりません。」と指摘される。

ここでようやくnpm run devすれば消えるなと思い実行しても、今度はparams.idが「プロパティ 'id' は型 'PageServerLoad' に存在しません。」と指摘される。

ということは「わざわざ後から自分で型を追加しないといけないのか?」と思って調べたところ、インターセクション型が使えそうだったので試してみたところ、無事警告が消えた。

/sveltekit-test/src/routes/sample/[id]/+page.server.ts
import type { PageServerLoad } from './$types.js';

// インターセクション型で指定
type Params = PageServerLoad & { id: string }

export async function load({ params }: { params: Params }) {
  console.log(params.id);

  return {
    params
  };
}

けがの功名

全体的には無駄な時間だったが、インターセクション型を知ることができて良かった。インターセクション型については下記の記事が面白い。
https://qiita.com/ist-ko-su/items/af8224f7571817fbb9bd

Discussion