Typescript error: property '$prismic' does not exist on type 'CombinedVueInstance'

I'm new to Typescript so there may be some setup I missed. When using this.$prismic in components, either in the fetch() hook (sadly can't use asyncData on component) or in methods, I get these errors:

                                  11:30:31ue:37:14
TS2339: Property '$prismic' does not exist on type 'CombinedVueInstance<Vue, unknown, { fullHtml(image: { image: { url: String; alt: String; }; caption: String; }): String; }, unknown, Readonly<{ slice: any; }>>'.
    35 |     }): String {
    36 |       return `<img src="${image.image.url}" alt="${image.image.alt}">
  > 37 |       ${this.$prismic.asHtml(image.caption)}`
       |              ^^^^^^^^
    38 |     },
    39 |   },
    40 | })

ERROR in components/Navbar.vue:17:26
TS7016: Could not find a declaration file for module 'vue-fragment'. 'F:/Projects/website-musicandmore/node_modules/vue-fragment/dist/vue-fragment.min.js' implicitly has an 'any' type.    
  Try `npm install @types/vue-fragment` if it exists or add a new declaration (.d.ts) file containing `declare module 'vue-fragment';`
    15 | <script lang="ts">
    16 | import Vue from 'vue'
  > 17 | import { Fragment } from 'vue-fragment'
       |                          ^^^^^^^^^^^^^^
    18 |
    19 | export default Vue.extend({
    20 |   components: {

ERROR in components/Navbar.vue:26:36
TS2339: Property '$prismic' does not exist on type 'CombinedVueInstance<Vue, { pages: never[]; }, unknown, unknown, Readonly<Record<never, any>>>'.
    24 |   async fetch() {
    25 |     try {
  > 26 |       let { results } = await this.$prismic.api.query([
       |                                    ^^^^^^^^
    27 |         this.$prismic.predicates.at('document.type', 'pages'),
    28 |       ])
    29 |

ERROR in components/Navbar.vue:27:14
TS2339: Property '$prismic' does not exist on type 'CombinedVueInstance<Vue, { pages: never[]; }, unknown, unknown, Readonly<Record<never, any>>>'.
    25 |     try {
    26 |       let { results } = await this.$prismic.api.query([
  > 27 |         this.$prismic.predicates.at('document.type', 'pages'),
       |              ^^^^^^^^
    28 |       ])
    29 |
    30 |       results = results.sort(


i Waiting for file changes                                                          11:30:33  
i Memory usage: 683 MB (RSS: 797 MB)                                                11:30:33  
i Listening on: http://localhost:3000/                                              11:30:33

Of course as soon as I post the question, I find the solution. On this github issue, user lesharris shares the solution: create a type in types/prismic.d.ts, add to the include key in tsconfig.json, and we're off. This fixed all my leftover errors. Copied the files here:

types/prismic.d.ts

import { getApi } from 'prismic-javascript'
import { DefaultClient } from 'prismic-javascript/d.ts/client'

import Vue from 'vue'

type ThenArg<T> = T extends Promise<infer U> ? U : T
type PrismicAPIPromise = ReturnType<typeof getApi>
type PrismicAPI = ThenArg<PrismicAPIPromise>

type ElementType =
  | 'heading1'
  | 'heading2'
  | 'heading3'
  | 'heading4'
  | 'heading5'
  | 'heading6'
  | 'paragraph'
  | 'preformatted'
  | 'strong'
  | 'em'
  | 'list-item'
  | 'o-list-item'
  | 'group-list-item'
  | 'group-o-list-item'
  | 'image'
  | 'embed'
  | 'hyperlink'
  | 'label'
  | 'span'

type Elements = { [key in ElementType]: string }

type HTMLSerializer<T> = (type: ElementType, element: any, text: string | null, children: T[], index: number) => T

interface RichText {
  Elements: Elements
  asHtml(richText: any, linkResolver?: (doc: any) => string, serializer?: HTMLSerializer<string>): string
  asText(richText: any, joinString?: string): string
}

interface Link {
  url(link: any, linkResolver?: (doc: any) => string): string
}

interface VuePrismic {
  endpoint: string
  linkResolver: (doc: any) => string
  htmlSerializer: HTMLSerializer<string>
  client: DefaultClient
  richTextAsPlain: (field: string) => string
}

type PrismicVue<T> = VuePrismic & T

declare module 'vue/types/vue' {
  interface Vue {
    $prismic: PrismicVue<PrismicAPI>
  }
}

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"]
  },

  // This is the line I was missing in 
  // addition to the entire type declaration.
  "include": ["types/**/*.ts"],

  "exclude": ["node_modules", ".nuxt", "dist"]
}
1 Like

Hello Jonathan,

I'm glad that you resolved this issue. Let us know if you have any doubt.

Thanks,
Priyanka

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.