Skip to content

TypeScript with Vue

TypeScript adds types to JavaScript. You write down which shape a value has, and a tool checks before the app starts whether the code fits. The course uses JavaScript, but create-vue asks whether you want TypeScript when it creates a project. In a project with TypeScript, every single file component starts with <script setup lang="ts">.

According to the project assignment, TypeScript throughout earns one bonus point. It pays off as soon as your project has more than a handful of components or gets data from an API. The editor then tells you while you type when a prop is missing, an event passes the wrong data or a field of the API has a different name. Plan some extra time, because you describe the types yourself once. Vite only translates TypeScript and checks no types, that is the job of vue-tsc.

The example under optional/typescript/en is a simplified catalog in TypeScript, with cards, search and favorites as in parts 3 to 5. An interface describes a thing the way the course API delivers it.

types.ts
// One thing of the catalog, as the course API delivers it
export interface Item {
id: number
name: string
category: string
deposit: number
availableFrom: string | null
}

The card declares its props and its event with types instead of objects like { type: Boolean }. favorite = false in the destructured props sets the default. defineEmits describes the event as a list of the values it passes along.

ItemCard.vue
<script setup lang="ts">
import type { Item } from '../types'
// The types describe the props and the events, vue-tsc checks every use of the component
const { item, favorite = false } = defineProps<{
item: Item
favorite?: boolean
}>()
const emit = defineEmits<{
toggleFavorite: [id: number]
}>()
</script>

In App.vue, ref only needs a type where the initial value does not reveal it. An empty array would otherwise have the type never[], and no value could go into it.

App.vue
<script setup lang="ts">
import { computed, ref } from 'vue'
import items from '../data/items.json'
import { search } from './catalog'
import ItemCard from './components/ItemCard.vue'
import type { Item } from './types'
const catalog: Item[] = items
const query = ref('')
// Without the type argument the empty array would be never[]
const favorites = ref<number[]>([])
const hits = computed(() => search(catalog, query.value))
function toggleFavorite(id: number) {
favorites.value = favorites.value.includes(id) ? favorites.value.filter((favorite) => favorite !== id) : [...favorites.value, id]
}
</script>

npm run type-check starts vue-tsc. If the template passes a string instead of a boolean as favorite to the card, vue-tsc reports the error with its line and column.

src/App.vue(28,33): error TS2322: Type 'string' is not assignable to type 'boolean | undefined'.

npm run build checks the types first and only builds afterwards. Watch the version of TypeScript. TypeScript 7 is a new implementation in Go that vue-tsc does not run with, and the TypeScript team advises projects with Vue to stay on version 6 for now. That is why the example uses 6.0.3. If you install TypeScript without a version, you get version 7 and vue-tsc stops.

Text and figures are licensed under CC BY-SA 4.0, the code under the MIT License and the course data under CC0 1.0. The figures use the font Kalam under the SIL Open Font License 1.1. The sources are on GitHub.