リンク
定義からリンクを作れるようになります。クエリは既定値を省いた形にそろい、パスはルート表で型検査できます。
このページの内容
hrefとsearch
listState.href('/products');
// '/products'
listState.href('/products', { inStock: true, page: 2 });
// '/products?inStock=true&page=2'
listState.search({ page: 2 });
// 'page=2'href(path, values?)は、定義からリンクを作ります。指定しなかったフィールドは既定値として扱い、既定値のままのフィールドはクエリから省きます。できるURLの形はURLを見てください。
search(values?)は、?を付けずにクエリ文字列だけを返します。パスを自分で組み立てるときに使います。たとえば、ダウンロードのURLに一覧と同じ条件を付けるときです。
返り値の型は、渡したパスをリテラルのまま残します。リンクを受け取る側の型検査(Next.jsの<Link>など)は、この型からクエリを除いてパスを確かめます。entryだけの定義では、hrefはクエリの無いリンクを返し、searchは空の文字列を返します。URLで表せない値を渡すと、どちらもhas no URL serializationを含むエラーになります。
Viteのbase
listState.href('/products', { page: 2 });
// '/docs/products?page=2'hrefに渡すパスは、ルート表のパターンと同じくbaseを含めずに書きます。返るリンクには、Viteのbaseが前に付きます。baseが'/docs/'なら、'/docs/products?page=2'になります。
@k8ordo/routerのhrefが返したリンクには、すでにbaseが付いているので渡さないでください。
Viteの外、たとえばNext.jsではimport.meta.envが無いので何も付けません。basePathは、そのフレームワークの<Link>が付けます。
パスの型検査
src/k8ordo.d.tsimport type { routes } from './routes';
declare module '@k8ordo/router' {
interface Register {
routes: typeof routes;
}
}
declare module '@k8ordo/state' {
interface Register {
routes: typeof routes;
}
}Registerを一度拡張すると、アプリの中のすべてのhrefが、ルート表に無いパスを型エラーにします。routes: typeof routesの1行は、@k8ordo/routerのパスの型検査の拡張と同じです。@k8ordo/frameworkでは、この宣言がsrc/routes/から.k8ordo/register.gen.tsに生成されるので、自分では書きません。生成されるのは、アプリ自身のpackage.jsonのdependenciesかdevDependenciesに@k8ordo/stateがあるときです。ほかのパッケージを経由した依存は数えません。
パスは、表のパターンとセグメントごとに照合します。固定のセグメントは、パターンと同じ綴りが要ります。:paramのセグメントには、空でない1セグメントなら何でも入ります。テンプレートリテラルの${string}も通ります。*を含むパターンには、リンクできません。どのパターンにも当たらないパスは型エラーです。/:localeで始まる表でも、'/ja/nowhere'は拒まれます。
検査は@k8ordo/routerのNavigablePathを型として使うだけです。ルーターは任意のpeerのままで、実行時には読み込まれません。
types/k8ordo.d.tsimport type { Route } from 'next';
declare module '@k8ordo/state' {
interface Register {
path: Route;
}
}@k8ordo/router以外のルーターには渡せる表が無いので、そのルーターのパスのunionをpathに登録します。Next.jsならnextのRouteです。routesとpathの両方があれば、routesが優先されます。どちらも無ければ、/で始まる文字列が何でも通ります。
落とし穴
Registerの拡張はアプリの中でだけ行ってください。共有のライブラリで拡張すると、その制約が使う側のすべてに及びます。