I am writing a Nuxt application in TypeScript. I have encountered a problem when trying to access $i18n object on Nuxt. I am getting a warning in VS Code saying:
Property '$i18n' does not exist on type 'MyClass'.
My script part in the component code is like the following:
<script lang="ts">
import { Vue, Component, Prop } from 'vue-property-decorator'
import ILocale from '~/types/vue/Locales'
@Component
export default class MyClass extends Vue {
@Prop({ type: Boolean, default: true }) showLanguageSwitch!: boolean
get availableLocales(): ILocale[] {
return this.$i18n.locales.filter((l) => l.code !== this.$i18n.locale)
}
}
</script>
I have a shim file in the root of the project:
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}
Is it the place where I should extend the interface? How do I actually do it as Vue
is not TS interface but a class definition with its own type.
The only thing that worked so far was adding a private property explicitly on MyClass
but then it complains about lack of initialisation and it feels wrong anyway. All other common properties of Vue are recognised byt TS, like $fetch, $config etc.
TS config:
{
"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"
]
},
"exclude": [
"node_modules"
]
}
Nuxt config:
export default {
head: {
htmlAttrs: {
lang: 'en',
},
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' },
],
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
},
publicRuntimeConfig: {},
css: [
'~assets/scss/fonts.scss',
'~assets/scss/variables.scss',
'~assets/scss/mixins.scss',
'~assets/scss/reset.scss',
'~assets/scss/typography.scss',
],
i18n: {
lazy: true,
langDir: 'i18n/',
locales: [
{
code: 'en',
iso: 'en',
file: 'en.json',
name: 'English',
},
{
code: 'de-DE',
iso: 'de-DE',
file: 'de.json',
name: 'Deutsch',
},
],
defaultLocale: 'en',
vueI18n: {
fallbackLocale: 'en',
},
seo: true,
strategy: 'prefix_except_default',
},
plugins: ['~/plugins/jsonld', '~/plugins/helpers'],
components: true,
buildModules: ['@nuxtjs/eslint-module', '@nuxt/typescript-build'],
modules: [
'@nuxtjs/axios',
'@nuxtjs/style-resources',
'nuxt-i18n',
'@nuxtjs/sitemap',
],
axios: {},
server: {
port: 3000,
host: '0.0.0.0',
},
router: {
middleware: ['langRedirect', 'seoMiddleware'],
trailingSlash: true,
},
serverMiddleware: [
'~/server-middleware/redirectApex.js',
{ path: '/api', handler: '~/server-middleware/rest.js' },
],
build: {},
styleResources: {
scss: [
'~assets/scss/fonts.scss',
'~assets/scss/variables.scss',
'~assets/scss/mixins.scss',
'~assets/scss/reset.scss',
'~assets/scss/typography.scss',
],
},
}
(EDIT) Correct function now after loading the nuxt-18n
types:
get availableLocales(): NuxtVueI18n.Options.LocaleObject[] {
if (!this.$i18n.locales) {
return []
}
return (this.$i18n.locales as NuxtVueI18n.Options.LocaleObject[]).filter(
(l) => l.code !== this.$i18n.locale
)
}