Overview
Using Vue with TypeScript
Section titled “Using Vue with TypeScript”A type system like TypeScript can detect many common errors via static analysis at build time. This reduces the chance of runtime errors in production, and also allows us to more confidently refactor code in large-scale applications. TypeScript also improves developer ergonomics via type-based auto-completion in IDEs.
Vue is written in TypeScript itself and provides first-class TypeScript support. All official Vue packages come with bundled type declarations that should work out-of-the-box.
Project Setup
Section titled “Project Setup”create-vue, the official project scaffolding tool, offers the options to scaffold a Vite-powered, TypeScript-ready Vue project.
Overview
Section titled “Overview”With a Vite-based setup, the dev server and the bundler are transpilation-only and do not perform any type-checking. This ensures the Vite dev server stays blazing fast even when using TypeScript.
- During development, we recommend relying on a good IDE setup for instant feedback on type errors.
- If using SFCs, use the
vue-tscutility for command line type checking and type declaration generation. vue-tscis a wrapper aroundtsc, TypeScript’s own command line interface. It works similarly totscexcept that it supports Vue SFCs in addition to TypeScript files.- You can run
vue-tscin watch mode in parallel to the Vite dev server, or use a Vite plugin likevite-plugin-checkerwhich runs the checks in a separate worker thread.
Vue CLI also provides TypeScript support, but is no longer recommended.
IDE Support
Section titled “IDE Support”- Visual Studio Code (VS Code) is strongly recommended for its great out-of-the-box support for TypeScript.
- Vue - Official (previously Volar) is the official VS Code extension that provides TypeScript support inside Vue SFCs, along with many other great features.
TIP: Vue - Official extension replaces Vetur, our previous official VS Code extension for Vue 2. If you have Vetur currently installed, make sure to disable it in Vue 3 projects.
- WebStorm also provides out-of-the-box support for both TypeScript and Vue. Other JetBrains IDEs support them too, either out of the box or via a free plugin.
Configuring tsconfig.json
Section titled “Configuring tsconfig.json”Projects scaffolded via create-vue include pre-configured tsconfig.json. The base config is abstracted in the @vue/tsconfig package. Inside the project, we use Project References to ensure correct types for code running in different environments (e.g. app code and test code should have different global variables).
When configuring tsconfig.json manually, some notable options include:
compilerOptions.isolatedModulesis set totruebecause Vite uses esbuild for transpiling TypeScript and is subject to single-file transpile limitations.compilerOptions.verbatimModuleSyntaxis a superset ofisolatedModulesand is a good choice too - it’s what@vue/tsconfiguses.- If you’re using Options API, you need to set
compilerOptions.stricttotrue(or at least enablecompilerOptions.noImplicitThis, which is a part of thestrictflag) to leverage type checking ofthisin component options. - If you have configured resolver aliases in your build tool, for example the
@/*alias configured by default in acreate-vueproject, you need to also configure it for TypeScript viacompilerOptions.paths. - If you intend to use TSX with Vue, set
compilerOptions.jsxto"preserve"andcompilerOptions.jsxImportSourceto"vue".
General Usage Notes
Section titled “General Usage Notes”defineComponent()
Section titled “defineComponent()”To let TypeScript properly infer types inside component options, we need to define components with defineComponent():
import { defineComponent } from 'vue'
export default defineComponent({ // type inference enabled props: { name: String, msg: { type: String, required: true } }, data() { return { count: 1 } }, mounted() { this.name // type: string | undefined this.msg // type: string this.count // type: number }})defineComponent() also supports inferring the props passed to setup() when using Composition API without <script setup>:
import { defineComponent } from 'vue'
export default defineComponent({ // type inference enabled props: { message: String }, setup(props) { props.message // type: string | undefined }})See also:
TIP
defineComponent()also enables type inference for components defined in plain JavaScript.
Usage in Single-File Components
Section titled “Usage in Single-File Components”To use TypeScript in SFCs, add the lang="ts" attribute to <script> tags. When lang="ts" is present, all template expressions also enjoy stricter type checking.
<script lang="ts">import { defineComponent } from 'vue'
export default defineComponent({ data() { return { count: 1 } }})</script>
<template> <!-- type checking and auto-completion enabled --> {{ count.toFixed(2) }}</template>lang="ts" can also be used with <script setup>:
<script setup lang="ts">// TypeScript enabledimport { ref } from 'vue'const count = ref(1)</script>
<template> <!-- type checking and auto-completion enabled --> {{ count.toFixed(2) }}</template>TypeScript in Templates
Section titled “TypeScript in Templates”The <template> also supports TypeScript in binding expressions when <script lang="ts"> or <script setup lang="ts"> is used. This is useful in cases where you need to perform type casting in template expressions.
Here’s a contrived example:
<script setup lang="ts">let x: string | number = 1</script>
<template> <!-- error because x could be a string --> {{ x.toFixed(2) }}</template>This can be worked around with an inline type cast:
<script setup lang="ts">let x: string | number = 1</script>
<template> {{ (x as number).toFixed(2) }}</template>TIP
If using Vue CLI or a webpack-based setup, TypeScript in template expressions requires
vue-loader@^16.8.0.
Usage with TSX
Section titled “Usage with TSX”Vue also supports authoring components with JSX / TSX. Details are covered in the Render Function & JSX guide.
Generic Components
Section titled “Generic Components”Generic components are supported in two cases:
- In SFCs:
<script setup lang="ts">with thegenericattribute - Render function / JSX components:
defineComponent()’s function signature
<script setup lang="ts" generic="T">defineProps<{ items: T[] selected: T}>()</script>