3

I'm writing a couple of examples for work, and one that's hanging me up is injecting a service that's provided during Vue's bootstrapping.

This "works" (I can access it, it compiles, and runs), and there are no problems or complaints with my JavaScript version nor the Class-Component TypeScript version, but the compiler complains that this.sampleService doesn't exist in my component when using the Vue object API with TypeScript.

Am I missing something?

<template>
  <div class="app">
    {{message}} <fake-button :text="buttonText" @some-click-event="handleClickEvent"></fake-button>
  </div>
</template>

<style lang="scss">
  .app {
    $background-color: #9f9;
    $foreground-color: #000;
    background: $background-color;
    color: $foreground-color;
  }
</style>

<script lang="ts">
  import Vue from 'vue'

  const App = Vue.extend({
    components: {
      FakeButton: () => import('@client/components/fake-button/fake-button-object-typescript.vue')
    },
    data: function () {
      return {
        message: 'Hello World - App Object TypeScript',
        buttonText: 'Click Me'
      }
    },
    inject: {
      sampleService: 'sampleService'
    },
    methods: {
      handleClickEvent(someVal?: string) {
        console.log('App', 'handleClickEvent', someVal);
      }
    },
    beforeCreate() {
      console.log('App', 'beforeCreate');
    },
    created() {
      console.log('App', 'created');
    },
    mounted() {
      console.log('App', 'mounted');
      // TODO: While this compiles, TypeScript complains that it doesn't exist
      console.log('this.sampleService.getDate()', this.sampleService.getDate());
    }
  });

  export default App;
</script>

ERROR in vue-test/src/client/containers/app/app-object-typescript.vue.ts
    [tsl] ERROR in vue-test/src/client/containers/app/app-object-typescript.vue.ts(35,56)
          TS2339: Property 'sampleService' does not exist on type 'CombinedVueInstance<Vue, { message: string; buttonText: string; }, { handleClickEvent(someVal?: s...'.

2 Answers2

0

My solution for this problem was to create a interface for the injection. In you example that would be something like the follwing:

<script lang="ts">
import { SampleServiceInjection } from '...';

const App = ( Vue as VueConstructor<Vue & SampleServiceInjection> ).extend({
  inject: {
    sampleService: 'sampleService'
  } as Record<keyof SampleServiceInjection, string>,
  // etc.
});
</script>

You can use that very interface in component that provides the service as well:

export interface SampleServiceInjection {
  sampleService: SampleService; // or whatever type your service has
}

export default Vue.extend({
  provide(): SampleServiceInjection {
    return {
      sampleService: new SampleService(),
    };
  },
  // etc.
});
Michael Große
  • 1,818
  • 1
  • 16
  • 20
-1

Try adding provide. Check example below. I would suggest using vue-property-decorator since your are leveraging typescript.

inject: {
      sampleService: 'sampleService'
    },
provide () {
    return {
      sampleService: this.sampleService,
    }
  }
Jeremy Walters
  • 2,081
  • 16
  • 28