TypeScript Best Practices for Vue Developers
Discover essential TypeScript patterns and best practices specifically tailored for Vue.js development to write more robust applications.
TypeScript Best Practices for Vue Developers
TypeScript has become an essential tool for building robust Vue applications. Here are the best practices every Vue developer should know when working with TypeScript.
1. Define Component Props with Interfaces
Always use interfaces to define your component props:
interface UserProps {
id: number
name: string
email: string
isActive?: boolean
}
export default defineComponent({
props: {
user: {
type: Object as PropType<UserProps>,
required: true
}
}
})
With
<script setup>
interface Props {
user: UserProps
showDetails?: boolean
}
const props = withDefaults(defineProps<Props>(), {
showDetails: false
})
2. Type Your Composables
Make your composables type-safe:
interface UseApiReturn<T> {
data: Ref<T | null>
loading: Ref<boolean>
error: Ref<string | null>
fetch: () => Promise<void>
}
export function useApi<T>(url: string): UseApiReturn<T> {
const data = ref<T | null>(null)
const loading = ref(false)
const error = ref<string | null>(null)
const fetch = async () => {
loading.value = true
error.value = null
try {
const response = await $fetch<T>(url)
data.value = response
} catch (err) {
error.value = err instanceof Error ? err.message : 'Unknown error'
} finally {
loading.value = false
}
}
return {
data,
loading,
error,
fetch
}
}
3. Use Generic Components
Create reusable generic components:
<script setup lang="ts" generic="T">
interface Props {
items: T[]
keyField: keyof T
displayField: keyof T
}
const props = defineProps<Props>()
const emit = defineEmits<{
select: [item: T]
}>()
</script>
<template>
<ul>
<li
v-for="item in items"
:key="String(item[keyField])"
@click="emit('select', item)"
>
{{ item[displayField] }}
</li>
</ul>
</template>
4. Strict Type Checking Configuration
Configure TypeScript strictly in your
tsconfig.json
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"exactOptionalPropertyTypes": true
}
}
5. Type Your Store (Pinia)
If using Pinia, type your stores properly:
interface UserState {
users: User[]
currentUser: User | null
loading: boolean
}
export const useUserStore = defineStore('user', {
state: (): UserState => ({
users: [],
currentUser: null,
loading: false
}),
getters: {
activeUsers: (state): User[] =>
state.users.filter(user => user.isActive)
},
actions: {
async fetchUsers(): Promise<void> {
this.loading = true
try {
this.users = await api.getUsers()
} finally {
this.loading = false
}
}
}
})
Conclusion
TypeScript significantly improves the development experience and code quality in Vue applications. By following these best practices, you'll write more maintainable and error-free code.
Remember: start with basic typing and gradually add more sophisticated types as your application grows!