Open1

TypeScript+Nuxt3 defineNuxtPluginで定義した関数の型付けメモ

yunayuna

内容

TypeScript+Nuxt3 の環境で、TS初心者が
defineNuxtPluginにて定義した関数に、型を設定するのにハマったのでメモしておきます。

前提

TypeScriptチェックのための基本的なモジュールを入れて、設定をしておく

bun add -D typescript
bun add -D vue-tsc
#以下はいらないかも?
bun add -D @vue/runtime-core @vue/runtime-dom
bun add -D @volar/vue-language-core @volar/vue-typescript
nuxt.config.ts
typescript: {
    strict: true,
    typeCheck: true,
    shim: true,
    tsConfig: {
      include: ['./**/types/**/*', './types/**/*']
    },
    compilerOptions: {
      types: [
        "bun-types",
        "@vue/runtime-core",
        "@vue/runtime-dom",
        "@volar/vue-language-core",
        "@volar/vue-typescript"
      ]
    }
  },

この状態で、サーバー起動すれば、型チェックしてくれますが、
チェックだけしたい場合は、これでもOKです。

npx nuxi typecheck

plugin定義ファイル

型が分かりやすいように、関数を一度constで定義してから、
provideしています。

plugins/samplePlugin.ts
export default defineNuxtPlugin(() => {
  const config = useRuntimeConfig();
  const API_BASE = makeApiBase(config);
  
  
  const fetchGet = async <T = any>(url: string, data: Record<string, any> = {}, option: FetchOption = {}): Promise<T> => {
    const token = await auth();

    if (data && Object.keys(data).length > 0) {
      if (url.indexOf("?") >= 0) {
        url = url + "&" + query(data);
      } else {
        url = url + "?" + query(data);
      }
    }
    const requestOptions = {
      method: "GET" as const,
      headers: Object.assign(
        {
          Authorization: token?.accessToken
            ? "Bearer " + token.accessToken
            : "",
        },
        DEFAULT_HEADERS
      ),
    };
    console.log("fetch!:", API_BASE() + url);
    return $fetch(API_BASE() + url, Object.assign({}, requestOptions, option)) as Promise<T>;
  }
  // nuxtApp.provide("fetchGet", $fetchGet);


  return {
    provide: {
      fetchGet: fetchGet,
    }
  }
});

型定義ファイルの設定

ハマったポイントは、
この型定義ファイルのdeclare module名で、
'nuxt/app' を指定ししないと、template内やmiddleware内でuseNuxtApp()した時、
定義した関数にうまく型が設定されませんでした。
'#app'は、TypeScriptのpathsによるエイリアスとのことで、必要なのか分かりませんが、
とりあえず残しておきました。

参考:
https://scrapbox.io/tascript/【Nuxt3】useNuxtAppの参照先「%23app」って一体何者なの?

types/nuxt.d.ts
interface CustomNuxtApp {
  $fetchGet: (url: string, data?: Record<string, any>, option?: any) => Promise<any>
}
//Nuxtの内部ビルドシステムで解決される特殊なパス、主にプラグインシステムで使用される
declare module '#app' {
  interface NuxtApp extends CustomNuxtApp {}
}

//実際のnpmパッケージパスで、TypeScriptが直接解決できるパス
declare module 'nuxt/app' {
  interface NuxtApp extends CustomNuxtApp {}
}
export {}