LoginSignup
0
0
お題は不問!Qiita Engineer Festa 2024で記事投稿!
Qiita Engineer Festa20242024年7月17日まで開催中!

Vue Routeのqueryの型がややこしくなってたので簡単に取れるようにした

Last updated at Posted at 2024-06-13

Vue3.4.27Nuxt3.12.1で開発しようとしてuseRoute().query.hogeを変数に入れようとすると、型エラーが...
image.png

LocationQueryValue? 見慣れない型だな:thinking:

Vue3.4.15Nuxt3.11.2で開発していた頃には見かけなかったので、ここから先述のバージョンの間に更新されたものと思われます。

確認したところ、↓こんな感じの型関係になっているようです。

export declare function useRoute(): RouteLocationNormalizedLoaded;
// ↓
export declare interface RouteLocationNormalizedLoaded extends _RouteLocationBase {
    matched: RouteLocationMatched[];
}
// ↓
export declare interface _RouteLocationBase extends Pick<MatcherLocation, 'name' | 'path' | 'params' | 'meta'> {
    // 省略
    query: LocationQuery;
    // 省略
}
// ↓
export declare type LocationQuery = Record<string, LocationQueryValue | LocationQueryValue[]>;
// ↓
export declare type LocationQueryValue = string | null;

なので、useRoute().query.hogeみたいに取得すると最終的には
string | null | (string | null)[]型が取得できます。


ここで困ったことが2点あります。

  • LocationQuery型はRecordなので存在しないキーを指定するとundefinedが返ってきますが、useRoute().query.hogeの型推論はLocationQueryValue | LocationQueryValue[]になっているためundefinedが含まれない
  • queryの値が配列である場合も考慮されていますが、私の場合配列で渡すことはない想定なので、毎回配列である可能性を除外して扱わないといけない

上記の対策コードを各query使用箇所に書くのはかなり冗長なので、Nuxtのutilsで定義しました。

extractRouteQueryStr.ts
import { type LocationQueryValue } from "vue-router";

export default (
  queryValue: LocationQueryValue | LocationQueryValue[] | undefined
): string | undefined =>
  queryValue instanceof Array
    ? queryValue[0] ?? undefined
    : queryValue ?? undefined;

やっていることは簡単で、
1.配列なら配列の最初の要素を返す

※今回の私のコードだと配列は使わない想定なので「配列の最初の要素」というのは適当です
(使わないならundefinedだけ返すようにした方が良いかもしれない)

arr[0]の返り値はT | undefinedなので、queryValue[0]string | null | undefinedとなります。
これを?? undefinedすることで、nullの場合もundefinedに統一して返すようにしています。

2.配列でないならLocationQueryValueを返すが、この型の中身はstring | nullなので、1と同じく?? undefinedしてnullの場合でもundefinedで返す

です。

usage
const hoge = extractRouteQueryStr(useRoute().query.hoge);

image.png

上記コードは配列の場合を一切考慮していないので、配列の場合どう返すかや、undefinedではなくnullで返したいなどの場合は適宜カスタマイズが必要です。

私の場合は、queryの値を受け取る関数を以下のような感じで定義していて、
nullをそのままにすると型定義が煩雑になるし、nullとundefindで関数の動作は変わらないので一律undefinedでいいかなという判断です。

const hoge = (
  redirect?: string,
  fuga: number,
  foo: string,
) => {
  //
}

// nullも考慮するとこうなる
const hoge = (
  redirect?: string | null
  fuga: number,
  foo: string,
) => {
  //
}

もしもっといいやり方があったら教えてください!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0