実現したいこと
nuxt-create-appを使って、typescriptベースの開発をしています。
scriptタグ内でnuxt-i18nのlocalePath関数を使いたいです。
発生している問題・エラーメッセージ
nuxt-property-decoratorを使いClass Componentな書き方をした際に、「Property 'localePath' does not exist on type 'default'.Vetur(2339)」というエラーが発生し、localePathが使えない問題が起きました。
※以下はお問い合わせ画面のsubmitボタンを押した際の処理です
extendしているVueクラスで参照している定義一覧を確認したところ、nuxt-property-decoratorに関する定義がありませんでした。
型定義ファイルの問題かと思ったのですが、node_modules/nuxt-i18n/types/vue.d.ts内で型定義されており、なぜ読み込まれないのか原因がわかりません。
どなたかアドバイスを頂けると幸いです。どうぞよろしくお願い致します。
環境
macOS Catalina 10.15.4
Node.js v10.16.3
npm 6.9.0
yarn 1.22.4(パッケージ管理はyarnを使っています)
※仮想環境やDockerは使っていません
ファイルの構造
│〜〜以下フォルダ〜〜
├── .git
├── .nuxt
├── .vscode
├── assets
├── components
│ └── validation
│ ├── FormValidationInput.vue
│ └── FormValidationTextarea.vue
├── layouts
├── locales
│ ├── en-US.json
│ ├── ja-JP.json
│ └── nuxt-i18n.config.ts
├── middleware
├── node_modules
├── pages
│ ├── contact
│ │ ├── index.vue ★<--エラーが発生しているファイル
│ │ └── thanks
│ │ └── index.vue
│ ├── index.vue
│ └── inspire.vue
├── plugins
│ ├── vee-validate.ts
│ └── vuetify.ts
├── static
├── store
├── test
│〜〜以下設定ファイルなど〜〜
├── .DS_Store
├── .babelrc
├── .editorconfig
├── .env
├── .eslintrc.js
├── .gitignore
├── .prettierrc
├── jest.config.js
├── jsconfig.json
├── nuxt.config.ts
├── package.json
├── README.md
├── stylelint.config.js
├── tsconfig.json
└── yarn.lock
node_modulesディレクトリのnuxt-i18nの構造
├── CHANGELOG.md
├── LICENSE
├── README.md
├── package.json
├── src
│ ├── helpers
│ │ ├── components.js
│ │ ├── constants.js
│ │ ├── routes.js
│ │ └── utils.js
│ ├── index.js
│ ├── plugins
│ │ ├── main.js
│ │ ├── routing.js
│ │ └── seo.js
│ └── templates
│ ├── middleware.js
│ ├── options.js
│ ├── seo-head.js
│ ├── utils-common.js
│ └── utils.js
├── types ★<--型定義ファイルは存在している
│ ├── index.d.ts
│ ├── nuxt-i18n.d.ts
│ └── vue.d.ts
該当のソースコード
pages/contact/index.vue
<template> <v-row justify="center" align="center" class="form"> <v-col cols="12" md="8" lg="6"> <v-card outlined> <v-row justify="center"> <v-col cols="10"> <v-card-title> <p>Contact us</p> </v-card-title> <v-divider></v-divider> <validation-observer ref="observer" v-slot="{ invalid }" tag="form" @submit.prevent="submit()" > <FormValidationInput rules="required|max:50" :label-message="$t('form.label.name')" input-type="text" form-component-name="name" max-length="50" :is-counter="true" :place-holder-message="$t('form.placeHolder.name')" :input-value.sync="inputName" > </FormValidationInput> <FormValidationInput rules="required|email|max:256" :label-message="$t('form.label.email')" input-type="email" form-component-name="email" max-length="256" :place-holder-message="$t('form.placeHolder.email')" :input-value.sync="inputEmail" /> <FormValidationTextarea rules="required|max:1000" :label-message="$t('form.label.message')" textarea-cols="20" textarea-rows="10" form-component-name="message" max-length="1000" :is-counter="true" :place-holder-message="$t('form.placeHolder.message')" :input-value.sync="inputMessage" > </FormValidationTextarea> <v-card-actions> <v-spacer /> <v-btn type="submit" :disabled="invalid" color="primary"> {{ $t('form.button') }} </v-btn> </v-card-actions> </validation-observer> </v-col> </v-row> </v-card> </v-col> </v-row> </template> <script lang="ts"> import { Component, Vue, Ref } from 'nuxt-property-decorator' import { ValidationObserver } from 'vee-validate' import FormValidationInput from '@/components/validation/FormValidationInput.vue' import FormValidationTextarea from '@/components/validation/FormValidationTextarea.vue' @Component({ components: { FormValidationInput, FormValidationTextarea } }) export default class extends Vue { inputName: String = '' inputEmail: String = '' inputMessage: String = '' @Ref() observer!: InstanceType<typeof ValidationObserver> async submit() { const isValid = await this.observer.validate() if (isValid) { this.inputName = '' this.inputEmail = '' this.inputMessage = '' requestAnimationFrame(() => { this.observer.reset() }) this.$router.push(this.localePath('/contact/thanks')) ★<--ここでlocalePathが読み込めない } } } </script>
その他関連ファイル
↓package.json
{ "name": "app", "version": "1.0.0", "description": "My cat's pajamas Nuxt.js project", "author": "user", "private": true, "scripts": { "dev": "nuxt-ts", "build": "nuxt-ts build", "generate": "nuxt-ts generate", "start": "nuxt-ts start", "lint": "eslint --ext .ts,.js,.vue --ignore-path .gitignore .", "lintfix": "eslint --fix --ext .ts,.js,.vue --ignore-path .gitignore .", "test": "jest" }, "lint-staged": { "*.{js,vue}": "yarn lint", "*.{css,vue}": "stylelint" }, "husky": { "hooks": { "pre-commit": "lint-staged" } }, "dependencies": { "@nuxt/typescript-runtime": "^0.4.0", "@nuxtjs/axios": "^5.3.6", "@nuxtjs/dotenv": "^1.4.0", "@nuxtjs/pwa": "^3.0.0-0", "nuxt": "^2.0.0", "nuxt-i18n": "^6.9.1", "nuxt-property-decorator": "^2.5.1", "vee-validate": "^3.2.5" }, "devDependencies": { "@nuxt/typescript-build": "^0.6.0", "@nuxtjs/eslint-config-typescript": "^1.0.0", "@nuxtjs/eslint-module": "^1.0.0", "@nuxtjs/stylelint-module": "^3.1.0", "@nuxtjs/vuetify": "^1.0.0", "@vue/test-utils": "^1.0.0-beta.27", "babel-eslint": "^10.0.1", "babel-jest": "^24.1.0", "eslint": "^6.1.0", "eslint-config-prettier": "^6.10.0", "eslint-plugin-nuxt": ">=0.4.2", "eslint-plugin-prettier": "^3.1.2", "husky": "^4.0.0", "jest": "^24.1.0", "lint-staged": "^10.0.0", "prettier": "^1.19.1", "stylelint": "^10.1.0", "ts-jest": "^25.0.0", "vue-jest": "^4.0.0-0" } }
↓nuxt.config.ts
import { Configuration } from '@nuxt/types' import i18n from './locales/nuxt-i18n.config' ★<--設定は外部から読み込んでいます const nuxtConfig: Configuration = { mode: 'universal', head: { titleTemplate: '%s - ' + process.env.npm_package_name, title: process.env.npm_package_name || '', meta: [ { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }, { hid: 'description', name: 'description', content: process.env.npm_package_description || '' } ], link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }] }, loading: { color: '#fff' }, css: [], plugins: ['plugins/vuetify', 'plugins/vee-validate'], buildModules: [ '@nuxt/typescript-build', '@nuxtjs/stylelint-module', '@nuxtjs/vuetify' ], modules: [ '@nuxtjs/axios', '@nuxtjs/pwa', '@nuxtjs/dotenv', ['nuxt-i18n', i18n] ★<--ここで外部ファイルを読み込んでいます ], axios: {}, vuetify: {}, build: { transpile: ['vee-validate/dist/rules'], extend(config, ctx) { if (ctx.isDev && ctx.isClient) { if (!config.module) return config.module.rules.push({ enforce: 'pre', test: /.(js|vue)$/, loader: 'eslint-loader', exclude: /(node_modules)/ }) } } } } module.exports = nuxtConfig
↓locales/nuxt-i18n.config.ts
export default { locales: [ { code: 'ja', iso: 'ja-JP', name: 'Japanese', file: 'ja-JP.json' }, { code: 'en', iso: 'en-US', name: 'English', file: 'en-US.json' } ], defaultLocale: 'en', strategy: 'prefix_and_default', detectBrowserLanguage: { useCookie: true }, lazy: true, langDir: 'locales/', vueI18n: { fallbackLocale: 'en' } }
↓tsconfig.json
{ "compilerOptions": { "target": "es2018", "module": "esnext", "moduleResolution": "node", "lib": [ "esnext", "esnext.asynciterable", "dom" ], "esModuleInterop": true, "allowJs": true, "sourceMap": true, "strict": true, "noEmit": true, "experimentalDecorators": true, "baseUrl": ".", "paths": { "~/*": [ "./*" ], "@/*": [ "./*" ] }, "types": [ "@types/node", "@nuxt/types", "@nuxtjs/vuetify", "vuetify", "nuxt-i18n" ★<--typescriptで型の追加 ], "resolveJsonModule": true, }, "exclude": [ "node_modules", ".nuxt", "dist" ] }
長文にお付き合い頂き、どうもありがとうございます。
あなたの回答
tips
プレビュー