2

In main.ts:

Vue.prototype.$http = http

Then in another component, inside a class i cannot call this.$http. I've read about augmented types, but can't figure out, where to put the file, how to call it, documentation isn't very clear on this topic: https://v2.vuejs.org/v2/guide/typescript.html#Augmenting-Types-for-Use-with-Plugins

So i've created a file 'src/types/vue.d.ts':

import Vue from 'vue'
import http from '@/http'

declare module 'vue/types/vue' {
  interface Vue {
    $http: http
  }
}

Contents of http.ts:

import axios from 'axios'

const HTTP = axios.create({
  baseURL: process.env.VUE_APP_API_URL
})

export default {
  login(credentials: any) {
    return HTTP.post('/auth', {
      account_email: credentials.email,
      account_password: credentials.password
    })
  }
}

But still i cannot use this.$http in components. My goal is to use this.$http which referencing to http.ts (axios module here) globally in every component.

4
  • But why do you want to augment the Vue type? Does every component need http functions? You could just create a helper class for http calls... Commented Apr 28, 2019 at 18:57
  • @Kokodoko, almost every component would require $http, it's annoying to import it in every single component. Commented Apr 28, 2019 at 18:59
  • 2
    Hopefully this help: mistergoodcat.com/post/vuejs-plugins-with-typescript Commented Apr 28, 2019 at 19:13
  • People, who minus me, please, explain why you do so. Commented Apr 29, 2019 at 9:54

1 Answer 1

5

Vue 3 Answer

Augmenting Vue to support your custom component properties are done through module augmentation. To add your $http declaration and support it you can create the vue-shim.d.ts file and augment vue/runtime-core

import axios from 'axios'

declare module '@vue/runtime-core' {
  export interface ComponentCustomProperties {
    $http: typeof axios
  }
}

Vue also asserts that for version 3, it's imperative you either import or export as the top level line of code in your ts file to ensure it's treated as a module:

Make sure the declaration file is a TypeScript module In order to take advantage of module augmentation, you will need to ensure there is at least one top-level import or export in your file, even if it is just export {}.

Now when you install your custom plugin, you can hang it off of the app.config.globalProperties object:

// my-custom-plugin.js
import axios from 'axios'
import http from 'plugins/http'

export default {
  install (app, options) {
    app.config.globalProperties.$http = http
  }
}

See below for the answer for Vue 2.

Vue 2 Answer

You can't declare the type of the $http as a value, instead make a new typing:

// http.d.ts

export default interface {
  login(credentials: any): PromiseLike<any> 
}

Then, in a file like types/vue.d.ts, augment the Vue constructor like:

import http from '@/types/http'

...
interface Vue {
  $http: http
}

Now make your http.ts by following the link in the comment above:

import _Vue from 'vue'
import axios from 'axios'

const http = {
  login(credentials: any) {
    return HTTP.post('/auth', {
      account_email: credentials.email,
      account_password: credentials.password
    })
  }
}

export function http(Vue: typeof _Vue): void {
  Vue.prototype.$http = http;
}        

and now you need to import that http.ts file and Vue.use it in something like main.ts

import Http from '@/http'

Vue.use(Http)

And now your components can consume your http plugin:

mounted() {
  this.$http.login(credentials)
  .then((response) => console.log(response))
  .catch((error) => console.warn(error))
}
Sign up to request clarification or add additional context in comments.

11 Comments

Do i have to duplicate each method (from http.ts) to interface? For example, if i have not just login, but login, getUsers, and so on. I have to describe them all in an interface? Also i can use interfaces directly in http.d.ts, right?
@AlexanderKim You definitely need to duplicate them. But you're not really duplicating them, you're typing them. You will want to do that for every method you wish to expose. You can use interfaces in http.d.ts, yes
Thanks, don't you think that TS is complicating life more than helping?
Not at all. Strong typing is extremely helpful, especially when bug hunting. I wouldn't trade it for the world. That and also clicking though functions and properties in your IDE to navigate around javascript is a dream come true.
OP is right here in his doubts. Why do we need to create external typings if we already use typescript? It is either typescript or vue bad design.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.