TypeScript is a JavaScript superset created by Microsoft which turns the loosely-typed language into a strictly-typed language. It can be summarized as ECMAScript 6 with optional type declarations.
Evan You, the creator of Vue.js, has stated that Vue.js 3.0’s codebase will be rewritten entirely in TypeScript.
In this tutorial, you will use @vue/cli
to generate a new Vue.js 2.0 application with TypeScript and build a Single-File Component (SFC).
To follow along with this article, you will need:
This tutorial was verified with Node v15.1.0, npm
v6.14.8, Vue.js v2.6.11, TypeScript v3.9.3, and @vue/cli
v4.5.0.
With Vue CLI 3+, it is possible to generate a new project with TypeScript already configured.
When using vue create
, you will be prompted with project configurations:
For the purposes of this tutorial, the configuration will require:
? Please pick a preset: Manually select features
In the selection prompt, choose TypeScript:
? Check the features needed for your project: TypeScript
Answer the following prompts:
? Choose a version of Vue.js that you want to start the project with 2.x
? Use class-style component syntax? No
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfi
lls, transpiling JSX)? Yes
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No
Note: While bootstrapping a new project, you will also be prompted with: Use class-style component syntax?
.
Back in February, Evan You abandoned the class style syntax for the Vue 3.0 core library altogether.
It is a popular choice, but for the purposes of this tutorial, select No.
If you would like to explore a project with class-style components, consult Writing Class-Based Components with Vue.js and TypeScript.
Selecting “TypeScript” will do several things. It will automatically add @vue/cli-plugin-typescript
to your project. It will replace main.js
with main.ts
. It will also add shims-tsx.d.ts
, and shims-vue.d.ts
.
Note: If you already have a Vue project created and want to add TypeScript support to it, you can do so with the following:
- vue add typescript
After generating your Vue project from the command line, you might have noticed the shims-vue.d.ts
file. That is the declaration file (.d.ts
).
A declaration file is a file that does not contain any executable code but contains descriptions of code that exists outside of the project files.
These are useful when using Node modules that do not contain any TypeScript interfaces, types, or declaration files. In a sense, the only purpose for these files is to tell TypeScript how to handle external code.
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}
This code essential tells the TypeScript compiler (and the IDE) how to handle .vue
files.
Once you have a Vue project with TypeScript, you can configure tsconfig.json
.
You can configure TypeScript to the needs of your team or project. There are many options that you can enable or disable with the use of a tsconfig.json
file. This file should live in the root directory of your project.
Feel free to experiment with these options to find which is most useful for you and your project.
noImplicitAny
, noImplicitThis
, noImplicitReturns
are options that will likely be beneficial to most situations:
noImplicitAny
: Raise error on expressions and declarations with an implied any
type. This will throw an error if an argument, const
, let
, or var
doesn’t have a type. This is more of a mental check on yourself to create custom data types for your code.noImplicitThis
: Similar to noImplicitAny
but will throw an error with the this
keyword. Another mental check to encourage you to type everything you can.noImplicitReturns
: Report an error when not all code paths in the function return a value. This helps ensure that all conditions in a given function with a return type, returns a value.Here is an example tsconfig.json
:
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"strict": true,
"noImplicitAny": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}
More information about tsconfig.json
is available in the official documentation.
In TypeScript, 12 basic types are supported:
boolean
number
string
array
object
tuple
enum
any
void
undefined
null
never
The more common types that you will be using are the primitive types: string
, number
, boolean
, null
, undefined
, and void
.
However, there will be times when you will need to create a custom data type. For those situations, you can create something that TypeScript calls an Interface
.
In your root directory, create a directory and name it types
:
- mkdir types
Inside this new directory, create a new file named, index.ts
. You can declare a new interface with the interface
keyword:
export interface User {
}
Note: It is considered best practice to use CamelCase for naming conventions.
From here, you can start defining the properties and value types that the object will have.
export interface User {
firstName: string,
lastName: string,
twitterHandle: string,
location: {
city: string,
state: string
}
}
In this example, you have an interface with an object inside it (location
). This can be broken up further by nesting interfaces.
You can also make any property optional by adding a ?
to it. This means that this property may or may not have a value.
Here are the previous index.ts
rewritten with those changes:
export interface User {
firstName: string,
lastName: string,
twitterHandle?: string,
location: Location
}
export interface Location {
city: string,
state: string
}
You can now use this custom data type in any Single-File Vue Component (.vue
) or TypeScript (.ts
) file.
Here is an example for App.vue
that uses the User
interface and displays the firstName
and lastName
:
<template>
<p>{{ fullName }}</p>
</template>
<script lang="ts">
export default {
name: 'Home',
data() {
return {
user: {}
}
},
computed: {
fullName() {
return `${this.user.firstName} ${this.user.lastName}`
}
},
mounted() {
this.user = {
firstName: `Sammy`,
lastName: `Shark`,
twitterHandle: `@digitalocean`,
location: {
city: `New York City`,
state: `NY`
}
}
}
}
</script>
In order to use TypeScript in this component, you will need to add a lang
attribute to the script
tag of your component. The value of that attribute should be ts
.
When using TypeScript in single-file Vue components, the Vue library must be imported so you can extend from it.
Since you will not be using the class-style syntax, you use the as
keyword to declare data as a data type.
For things like const
, let
, var
, or a function return type, you can define its type with the colon (:
).
After applying these changes to App.vue
, it now resembles:
<template>
<p>{{ fullName }}</p>
</template>
<script lang="ts">
import { User } from '../types'
export default Vue.extend({
name: 'Home',
data() {
return {
user: {} as User
}
},
computed: {
fullName(): string {
return `${this.user.firstName} ${this.user.lastName}`
}
},
mounted(): void {
this.user = {
firstName: `Sammy`,
lastName: `Shark`,
twitterHandle: `@digitalocean`,
location: {
city: `New York City`,
state: `NY`
}
}
}
})
</script>
This code imports the User
interface and declares reactive data
as type User
.
The computed
property returns a string
, so a string
type is defined. The mounted
hook returns nothing, so a void
type is defined. With these definitions in place, there will be no TypeScript errors when compiling.
Compile the application:
- npm run serve
When you open the result in a browser, you should observe the full name displayed.
TypeScript is JavaScript. With TypeScript, you can be as strict or as lenient as you want. It helps keep your code base consistent and scalable as your project continues to grow.
TypeScript is also heavily integrated with various popular IDEs and editors (including VS Code, WebStorm, Sublime, Vim, Atom, and more). With these editors, TypeScript works in the background, behind the scenes to provide real-time clues, suggestions, and previews of function arguments and return types.
All-in-all, it is a language that continues to find its way into more tools, libraries, and frameworks that developers use every day. It has a strong Open Source community and the backing of Microsoft.
If you’d like to learn more about TypeScript, check out our TypeScript topic page for exercises and programming projects.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Sign up for Infrastructure as a Newsletter.
Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Why the extension name is .vue when writing it in typescript? Is there a way to do it in proper typescript the same as angular and react typescript?
Why write
Isn’t ‘Home’ with quotes already enough to indicate that this value is a string?