Vue.js course Β· Module 15: TypeScript & Nuxt
TypeScript with Vue.js
In this lesson5
Welcome to the NOVA LAB Quantum Laboratory! Year 2087 - the space station systems demand the highest precision. Any error in a data type could lead to a catastrophe. That's why our engineers use TypeScript - a static type system that catches errors before the code even runs.
Why TypeScript with Vue?
TypeScript is a superset of JavaScript that adds static types. Combined with Vue 3, it gives us:
- Autocompletion in the code editor (IntelliSense)
- Error detection before running the application
- Better documentation - types describe the shape of data
- Refactoring - the editor understands the code structure
Setting Up a Vue Project with TypeScript
Creating a Vue project with TypeScript is simple thanks to Vite:
1npm create vite@latest nova-lab -- --template vue-tsVite automatically configures TypeScript and creates a tsconfig.json file:
1{
2 "compilerOptions": {
3 "target": "ES2020",
4 "module": "ESNext",
5 "moduleResolution": "bundler",
6 "strict": true,
7 "jsx": "preserve",
8 "paths": {
9 "@/*": ["./src/*"]
10 }
11 },
12 "include": ["src/**/*.ts", "src/**/*.vue"]
13}The lang="ts" Attribute
In Vue SFC (Single File Components), we add lang="ts" to the <script setup> block:
1<script setup lang="ts">
2import { ref } from 'vue'
3
4const stationName = ref<string>('NOVA LAB')
5const crewCount = ref<number>(42)
6const isOnline = ref<boolean>(true)
7</script>Without lang="ts", Vue treats the code as plain JavaScript. With lang="ts", the TypeScript compiler checks types and catches errors.
Basic Types in Vue
1<script setup lang="ts">
2import { ref } from 'vue'
3
4// Simple types
5const name: string = 'Mars Station'
6const year: number = 2087
7const active: boolean = true
8
9// Arrays
10const modules: string[] = ['Lab', 'Hangar', 'Bridge']
11const temperatures: number[] = [-63, -58, -71]
12
13// Ref with generic type
14const status = ref<string>('operational')
15const energy = ref<number>(98.5)
16</script>TypeScript automatically infers types, so you don't always have to specify them explicitly:
1const count = ref(0) // ref<number> - inferred automatically
2const label = ref('test') // ref<string> - inferred automaticallyExplicit typing is useful when the type cannot be inferred:
1const data = ref<string | null>(null) // can be string or nullTypeScript Interfaces
Interfaces define the shape of objects:
1interface CrewMember {
2 id: number
3 name: string
4 role: string
5 active: boolean
6}
7
8const engineer: CrewMember = {
9 id: 1,
10 name: 'Dr. Nova',
11 role: 'Chief Engineer',
12 active: true
13}Code for this lesson: App.vue
1<script setup lang="ts">
2import { ref } from 'vue'
3
4// Basic types
5const stationName = ref<string>('NOVA LAB')
6const crewCount = ref<number>(42)
7const isOnline = ref<boolean>(true)
8
9// Interface
10interface CrewMember {
11 id: number
12 name: string
13 role: string
14 active: boolean
15}
16
17// Typed array
18const crew = ref<CrewMember[]>([
19 { id: 1, name: 'Dr. Nova', role: 'Commander', active: true },
20 { id: 2, name: 'Atlas', role: 'Navigator', active: true },
21 { id: 3, name: 'Echo', role: 'Engineer', active: false }
22])
23
24// Union type
25const status = ref<'online' | 'offline' | 'maintenance'>('online')
26
27function toggleStatus() {
28 const states: Array<'online' | 'offline' | 'maintenance'> = ['online', 'offline', 'maintenance']
29 const idx = states.indexOf(status.value)
30 status.value = states[(idx + 1) % states.length]
31}
32</script>
33
34<template>
35 <div class="nova-lab">
36 <h1>{{ stationName }}</h1>
37 <p>Crew: {{ crewCount }} | Status: <span :class="status">{{ status }}</span></p>
38 <button @click="toggleStatus" class="btn">Toggle status</button>
39
40 <h2>Crew</h2>
41 <div v-for="member in crew" :key="member.id" class="card">
42 <strong>{{ member.name }}</strong> - {{ member.role }}
43 <span :class="member.active ? 'active' : 'inactive'">
44 {{ member.active ? 'Active' : 'Inactive' }}
45 </span>
46 </div>
47 </div>
48</template>
49
50<style scoped>
51.nova-lab {
52 background: #0a0e27;
53 color: #00ff88;
54 min-height: 100vh;
55 padding: 20px;
56 font-family: monospace;
57}
58h1 { color: #00ff88; margin-bottom: 5px; }
59h2 { color: #00b4d8; margin-top: 20px; }
60.btn {
61 background: #00b4d8;
62 color: white;
63 border: none;
64 padding: 8px 16px;
65 border-radius: 8px;
66 cursor: pointer;
67 margin: 10px 0;
68}
69.card {
70 background: rgba(0, 180, 216, 0.1);
71 border: 1px solid #00b4d8;
72 padding: 12px 16px;
73 margin: 6px 0;
74 border-radius: 8px;
75 display: flex;
76 justify-content: space-between;
77 align-items: center;
78}
79.online { color: #00ff88; }
80.offline { color: #e74c3c; }
81.maintenance { color: #f39c12; }
82.active { color: #00ff88; font-size: 12px; }
83.inactive { color: #e74c3c; font-size: 12px; }
84</style>Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. What is the main benefit of using TypeScript with Vue.js?
2. What attribute do we add to the <script setup> block to enable TypeScript?
These are 2 of 3 questions for this lesson. Solve the rest in the game.
Hands-on tasks in the game
- Code editor
Type ref as string, number, boolean and create an interface for a crew object.
- Click in order
Arrange the steps for configuring a Vue project with TypeScript:
- Code editor
Define a ModuleProps interface and use defineProps with a generic type.