Professional Documents
Culture Documents
Vue 3 With TS
Vue 3 With TS
TypeScript
Introduction
One of the big topics being discussed in Vue 3 is around
TypeScript. However, for those of us who haven’t jumped
on the TypeScript train yet, there is understandably a lot of
hesitancy when it comes to adding TypeScript to their
codebase. In this lesson, I’ll be addressing some of these
concerns to help provide another perspective when
evaluating whether Vue & TypeScript is a good
combination for your project or not.
Defining TypeScript
First, let’s take a minute to level set as far as what
TypeScript is.
With that said, let’s get into the pros and cons of adding
TypeScript to your Vue project.
The cost of
TypeScript
Like any additional dependency you add to your codebase,
the biggest cost is typically the learning curve required for
new developers to become productive with the new tool.
As more and more developers come into the world of
programming with JavaScript as their first language, this
means that there is a lot of new paradigms and things to
learn which can be very expensive to teams with tight
deadlines.
Is TypeScript worth
it?
Of course, while we’ve now demystified the use of static
types, that still leaves the question of whether it’s worth it
to add TypeScript to your codebase.
Large Codebases
When we look at Angular, which is a highly opinionated
framework that was designed primarily with enterprise
companies in mind, their decision to make TypeScript
mandatory is something worth considering.
What about
TypeScript support
in Vue?
One of the biggest hurdles that people encountered when
using TypeScript in Vue 2 was that while it was technically
possible, there was a rather high cost of entry and some
things didn’t work as well as they’d like. For example,
being able to easily detect types across Vuex was lacking
and people had to make various compromises to get it to
work.
TypeScript can be
progressively added
A misconception that many have is that TypeScript is all or
nothing. After all, if you’re going to use TypeScript,
shouldn’t your entire application be rewritten in it? The
reality is that this couldn’t be further from the truth. In
other words, just like how you can progressively migrate a
legacy app to Vue by dropping in a CDN package to add
Vue functionality, the same can be said of TypeScript.
Let’s ReVue
At the end of the day, it’s possible that TypeScript is not a
good fit for your project. And if that’s the case, that’s
perfectly okay! However, if it seems like TypeScript might
have a place in a future project, then be sure to stick
around as we dive into the fundamentals of working withe
TypeScript in Vue.
Setting Up
Vue 3 &
TypeScript
Introduction
In this lesson, we will be talking about how to setup a
brand new Vue project with TypeScript and how to add
TypeScript to an existing Vue 3 project.
Prerequisites
The first thing we need is the Vue CLI. If this is the first
time you’ve used Vue CLI, here are the basic steps for
getting setup:
Setting Up a New
Vue.js 3 +
TypeScript Project
Creating Our Project in Vue
CLI
Inside of your terminal, let’s create a new project by
running
When prompted to select a preset, let’s choose the options
manually to understand what’s going into our project by
using the arrow keys to select the third option: .
Adding TypeScript
to an Existing Vue
CLI Project
When working with an existing Vue CLI project, we can
make use of the TypeScript plugin by calling:
Once that’s done, you should see that your application now
has the boilerplate files (i.e., , , , , ) updated along with any
other JS files you might have. However, if you have other
components, they will not be updated since Vue CLI does
not want to make assumptions on whether it makes sense
to enhance components with TypeScript or not.
Final Thoughts
As we can see in this lesson, Vue CLI makes the process of
adding TypeScripts much easier since it takes care of a lot
of configuration that you would normally need to do
manually.
Creating
Components
with
TypeScript
Introduction
In the last lesson, we learned how to setup a project with
TypeScript and Vue CLI. In this lesson, we’ll take a look at what
changes have happened inside of our Single File Components.
TypeScript Changes
in Single File
Components
The Language Attribute
One of the most important changes that have happened in our
Single File Components (SFC) is that our block now contains a
attribute, which stands for language. This is more commonly
seen on the block where we declare the use of pre-processors
such as Sass.
defineComponent Method
One of the newer things that takes some getting used to in Vue
3 is the importing of helper methods. And while we typically
define components in Single File Components (SFC) by writing:
<script>
import EventCard from '../components/EventCard.vue'
import EventService from '../services/EventService'
export default {
name: 'EventList',
components: {
EventCard
},
data() {
return {
events: null
}
},
created() {
EventService.getEvents()
.then(response => {
this.events = response.data
})
.catch(error => {
console.log(error)
})
}
}
</script>
<script lang="ts">
import { defineComponent } from 'vue'
Challenge
For this lesson, I challenge you to upgrade the EventCard.vue
and EventDetails.vue components. You can find the starting
point for the challenge on the 03-challenge branch.
Good luck!
Type
Fundamental
s
Introduction
One of TypeScript’s fundamental concepts is the ability to
define static types that can be used to enhance development. In
this lesson, we will be covering some of the most useful types
that you should be aware of as you start your TypeScript
journey.
Overview of Types
Basic Types
As a quick review, common JavaScript types that we often
encounter in our code include:
● String
● Number
● Boolean
● Array
● Function
● Object
Function
When it comes to adding types to a function, there are a few
ways to do this. However, regardless of the methodology, there
are two key parts to keep in mind:
● Parameters
● Return
However, we’re not done yet! The one last thing we need to do
is to define what type of data we expect to get from the function,
which we do by using the colon (i.e., :) after the parameters.
Object
In TypeScript, objects are where things begin to get more
interesting, but before we get into those pieces, let’s start with
the fundamentals of how to define types on object values. In the
case of a person object:
let person = {
age: 20,
activeAvenger: true,
let person: {
name: string;
age: number;
activeAvenger: boolean;
powers: string[];
} = {
age: 20,
activeAvenger: true,
At first glance, this might look really odd. After all, it looks like
you’re defining the object twice. In addition, you might have also
noticed that the type is not a traditional object because there
are semi-colons (i.e., ;) instead of commas (i.e., ,).
Limitations of Predefined
Types
While a lot of incredible things has and can be built with
pre-defined types provided to us by JavaScript and TypeScript,
the reality is that there leaves something left to be desired when
providing more descriptive types.
Let’s ReVue
In this lesson, we covered fundamental knowledge of taking the
basic types that most JavaScript developers are already familiar
with and applying them as types with TypeScript. In the next
lesson, we’ll be learning how to use one of TypeScript’s most
useful feature: the ability to define custom types.
Defining
Custom
Types
Introduction
As we saw in the last lesson, predefined types are incredibly
helpful for a number of common scenarios. However, as
applications grow in size and complexity with unique
requirements, it’s inevitable that there will be a need for custom
types. And when you want to define custom types in TypeScript,
there are two methods that account for most scenarios early on:
type and interface.
What is ? type
And now when we apply it, we can ensure that all buttonType
variables have the correct value!
// TypeScript will report an error because this doesn't
exist in the type!
What is an interface ?
When getting started with interface, the way I like to think
about it is a way to define a type for an object. To show this in
action, let’s take a look at an object we defined In the last
lesson.
let person: {
name: string;
age: number;
activeAvenger: boolean;
powers: string[];
} = {
age: 20,
activeAvenger: true,
As we can see here, even though the data isn’t too complicated,
it’s already fairly verbose and adds clutter to our code. Wouldn’t
it be nice if it could look something like this instead?
age: 20,
activeAvenger: true,
powers: ['wall-crawl', 'spider-sense']
interface Hero = { }
interface Hero {
name: string;
age: number;
activeAvenger: boolean;
powers: string[];
And just like that, we can now define variables that will be
checked against the type Hero!
interface Hero {
name: string;
age: number;
activeAvenger: boolean;
powers: string[];
universe: string;
interface Hero {
name: string;
age: number;
activeAvenger: boolean;
powers: string[];
universe: ComicUniverse;
}
And just like that, we’ve now combined our interface and type
together!
Let’s ReVue
Thanks for watching, and I’ll see you in the next lesson.
Data with
Custom
Types
Introduction
Now that we know how to define custom types, it’s time for us to
apply our new abilities to Vue itself! To start, we will be taking a
look at the data option first.
The Problem
When we open up EventDetails.vue, one of the problems that
might not be immediately obvious for those of us who haven’t
used types before is that currently our editor cannot provide
much help in terms of what is valid or not.
📄 EventDetails.vue
<template>
<div v-if="event">
</div>
</template>
For example, while we reference event.id, there’s nothing to
inform us that this is an attribute that exists. In fact, the only way
to really check is to wait until the code runs. And while this
might not seem like a huge impediment at first, this can cause a
lot of issues when the data becomes more complex.
Introducing VueDX
So how do we get our editor to help us? Well, the first step is to
install a new VS Code extension called VueDX.
📄 EventDetails.vue
import { defineComponent } from 'vue'
name: 'EventDetails',
data() {
return {
event: null
},
})
So to fix this, let’s start by tracing back to how the Event type
should be structured. The way we do this is to trace our steps
back to where the data source is coming from, which is an API
call in EventService.ts
📄 EventService.vue
import axios from 'axios'
const apiClient = axios.create({
baseURL:
'<https://my-json-server.typicode.com/Code-Pop/Real-World
_Vue-3>',
withCredentials: false,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
})
"id": 123,
"time": "12:00",
With this, we can now say with confidence that events should
be an Array that contains a series of objects with the following
properties:
● id
● category
● title
● description
● location
● date
● time
● organizer
📄 types.ts
export interface EventItem {
id: number
category: string
title: string
description: string
location: string
date: string
time: string
organizer: string
}
To clarify, we could certainly dive deeper into refining the types
for the individual properties of EventItem, but for this lesson, I’ve
kept it simple for now.
📄 EventDetails.vue
import { defineComponent } from 'vue'
name: 'EventList',
data() {
return {
event: null
},
})
interface TodoItem {
label: string
complete: boolean
const futureTodoItem = {}
futureTodoItem.complete = false
interface TodoItem {
label: string
complete: boolean
}
futureTodoItem.complete = false
name: 'EventDetails',
data() {
return {
event: null
},
})
📄 EventDetails.vue
import { defineComponent } from 'vue'
name: 'EventDetails',
data() {
return {
event: {}
},
})
📄 EventDetails.vue
import { defineComponent } from 'vue'
import { EventItem } from '../types'
name: 'EventDetails',
data() {
return {
},
})
And just like that, we’ve now properly typed our data property!
Code Challenge
Now that you know how to add custom types to the data option,
checkout the 06-challenge branch and define the correct
custom type for EventList.vue.
Let’s ReVue
In this lesson, we’ve learned about the new VueDX extension,
what type assertions are, and how to use the new as keyword in
order to define custom types in our data option in Vue 3.
props: ['id']
})
props: {
id: {
type: Number,
required: true
},
})
Applying a Custom
Type to Props
Your first instinct from applying custom types to our data
property is probably to swap out Object for our EventItem type,
but this won’t work. After all, EventItem is a TypeScript type —
which means it is TypeScript specific — and not something that
JavaScript itself can evaluate.
Your next thought might be to use our new as keyword to assert
the type, and you would be close, but this won’t work either.
The reason for this is because with props in Vue, Vue provides
additional functionality to check props that go beyond
TypeScript. Before we can dive into this, we need to first learn
about TypeScript generics.
TypeScript Generics
At this point, we have learned how to type basic functions in
TypeScript.
newList.push(item)
return newList
}
With this, you get type safety, but the function is rather limiting
isn’t it? And if we were to rename it properly, we’d probably
want to call it addNumberToNumberList, but this wouldn’t be very
reusable then. So the question is, how would we make this
more reusable?
return newList
So out in other code bases, the same code above would look
like this:
return newList
Now that we know this, it’s time to get a little help from Vue to
finish our task!
props: {
event: {
required: true
},
})
So if you think about it another way, this is how we tell Vue that
the prop value should be a type of PropType and EventItem. And
just like that, you’ve now successfully added a custom type to
your prop!
Let’s Revue
In this lesson, we learned about the PropType helper method,
the concept of generics, and how we combine them with type
assertion to apply custom types to our props.
Computed &
Methods
with Custom
Types
As we begin to wrap up our journey together with the
fundamentals of using TypeScript with Vue 3, it’s time we
learned how to add custom types to computed properties and
methods.
<script lang="ts">
data() {
return {
events: []
},
methods: {
secondEvent() {
return this.events[1]
}
})
</script>
<script lang="ts">
data() {
return {
},
methods: {
secondEvent(): EventItem {
return this.events[1]
})
</script>
<script lang="ts">
data() {
return {
},
methods: {
secondEvent(): EventItem {
return this.events[1]
}
}
})
</script>
<script lang="ts">
data() {
return {
},
methods: {
addEvent(newEvent) {
this.events.push(newEvent)
})
</script>
In our addEvent function, we can see that it takes in a parameter
of newEvent and adds it to the events data that we’re tracking
inside of data().
addEvent(newEvent: EventItem) {
this.events.push(newEvent)
}
Adding Custom Types to the
Return Value of a Method
For this scenario, let’s change up the method to fetching the
second event:
secondEvent() {
return this.events[1]
secondEvent(): EventItem {
return this.events[1]
}
And with that, you know all you need to add custom types to
your methods!
Let’s ReVue
In this lesson, we’ve learned how to apply custom types to
computed properties by focusing on what is being returned. And
finally, for methods, we need to make sure we check whether
our parameters and return value need any custom types.