title: "Property '$i18n' does not exist on type X" in Nuxt application
body: <p>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:</p>
  <pre><code>Property '$i18n' does not exist on type 'MyClass'.
  </code></pre>
  <p>My script part in the component code is like the following:</p>
  <pre><code>&lt;script lang=&quot;ts&quot;&gt;
    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) =&gt; l.code !== this.$i18n.locale)
      }
    }
  &lt;/script&gt;
  </code></pre>
  <p>I have a shim file in the root of the project:</p>
  <pre><code>declare module '*.vue' {
    import Vue from 'vue'
    export default Vue
  }
  </code></pre>
  <p>Is it the place where I should extend the interface? How do I actually do it as <code>Vue</code> is not TS interface but a class definition with its own type.</p>
  <p>The only thing that worked so far was adding a private property explicitly on <code>MyClass</code> 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.</p>
  <p>TS config:</p>
  <pre><code>{
    &quot;compilerOptions&quot;: {
      &quot;target&quot;: &quot;ES2018&quot;,
      &quot;module&quot;: &quot;ESNext&quot;,
      &quot;moduleResolution&quot;: &quot;Node&quot;,
      &quot;lib&quot;: [
        &quot;ESNext&quot;,
        &quot;ESNext.AsyncIterable&quot;,
        &quot;DOM&quot;
      ],
      &quot;esModuleInterop&quot;: true,
      &quot;allowJs&quot;: true,
      &quot;sourceMap&quot;: true,
      &quot;strict&quot;: true,
      &quot;noEmit&quot;: true,
      &quot;experimentalDecorators&quot;: true,
      &quot;baseUrl&quot;: &quot;.&quot;,
      &quot;paths&quot;: {
        &quot;~/*&quot;: [
          &quot;./*&quot;
        ],
        &quot;@/*&quot;: [
          &quot;./*&quot;
        ]
      },
      &quot;types&quot;: [
        &quot;@types/node&quot;,
        &quot;@nuxt/types&quot;
      ]
    },
    &quot;exclude&quot;: [
      &quot;node_modules&quot;
    ]
  }
  </code></pre>
  <p>Nuxt config:</p>
  <pre><code>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',
      ],
    },
  }
  </code></pre>
  <p>(EDIT) Correct function now after loading the <code>nuxt-18n</code> types:</p>
  <pre><code>get availableLocales(): NuxtVueI18n.Options.LocaleObject[] {
    if (!this.$i18n.locales) {
      return []
    }
  
    return (this.$i18n.locales as NuxtVueI18n.Options.LocaleObject[]).filter(
      (l) =&gt; l.code !== this.$i18n.locale
    )
  }
  </code></pre>