DEV Community

Pacharapol Withayasakpunt
Pacharapol Withayasakpunt

Posted on

 

A guide to using TypeScript in Vue, with maximal VSCode IntelliSense

As a lover of TypeScript InteliSense and Vue, I have always tried to use TypeScript in Vue, but Vetur isn't as smart as it should...

So, I have found some fixes --

After, vue create <APP_NAME>

  • Change src/App.vue to src/pages/App/index.(tsx|css)
  • Change components/HelloWorld.vue to src/components/HelloWorld/index.(tsx|css)
  • Change .eslintrc.js to
module.exports = {
  parserOptions: {
    parser: '@typescript-eslint/parser',
    ecmaFeatures: {
      jsx: true,
    },
  },
}
Enter fullscreen mode Exit fullscreen mode

src/pages/App/index.tsx will be the following

import { Component, Vue } from 'vue-property-decorator'

import HelloWorld from '@/components/HelloWorld'

import './index.css'

@Component({
  components: {
    HelloWorld,
  },
})
export default class App extends Vue {
  render () {
    return (
      <div id="app">
        <img alt="Vue logo" src={ require('@/assets/logo.png') } />
        <HelloWorld props={ { msg: 'Welcome to Your Vue.js + TypeScript App' } } />
      </div>
    )
  }
}
Enter fullscreen mode Exit fullscreen mode

About src/components/HelloWorld/index.tsx, you could probably guess, but in short,

  • There needs to be a /> or a closing tag.
  • Props might not work properly. You need props={ { msg: 'Welcome to Your Vue.js + TypeScript App' } }.
  • Don't forget to add this.
  • require('@/assets/logo.png') seems to work because of some Webpack loader in Vue CLI.

TLDR / Take Home Message

  • Vetur in VSCode does not always work fully for TypeScript, especially in a Monorepo
    • The best fix is indeed, do not use TypeScript in *.vue
    • One of the workarounds is <script lang="ts" src="./index.ts">
  • Vue template string isn't as smart as TypeScript Intellisense.
    • The workaround is, do not use <template>. Use *.tsx (or *.jsx) instead.
  • It is still simple to reference foldered component if you filename is ./index.tsx
    • import HelloWorld from '@/components/HelloWorld' for example, will reference @/components/HelloWorld/index.tsx, will full IntelliSnese.
  • @angular/cli's ng generate component App doesn't even create a Single File Component, but instead create a single folder with multiple components.
./src/app/comp
├── comp.component.html
├── comp.component.scss
├── comp.component.spec.ts
└── comp.component.ts
Enter fullscreen mode Exit fullscreen mode

Summary

In summary, do not use *.vue, if you want a better IntelliSense. There are other approaches in component-based structure; like a folder.

Why does Vue adopt Single File Components at all, as it isn't necessarily better than Angular's?

I have also tried https://github.com/vuejs/jsx, but Vue CLI seems to already support JSX by default.

If you stuck somewhere, see this repo. I might also add Nuxt in the future.

GitHub logo patarapolw / vue-typescript-suggestions

An example repo for using TypeScript in Vue, with maximal VSCode suggestions

Top comments (1)

Collapse
 
michaelthiessen profile image
Michael Thiessen

I'd just like to add a couple updates to this for anyone reading this:

First, Volar has now replaced Vetur as the official Vue extension for VS Code in Vue 3.

Second, you may run into a weird error when using Volar and Typescript. Volar complains that TypeScript intellisense is disabled on template.

The solution to this is to add "jsx": "preserve" in the compilerOptions of your .tsconfig:

// .tsconfig
{
  "compilerOptions": {
    "jsx": "preserve"
  }
}
Enter fullscreen mode Exit fullscreen mode

I wrote about this solution on my blog if you happen to run into this and want more details on this error.

Interested in expanding your horizon for programming languages, but not sure where to start?

Check out this great DEV post:

Hello world in 10 different languages