TypeScript поддержка

TypeScript во Vue.js используется для строгой типизации данных, компонентов и логики приложения. Он позволяет выявлять ошибки на этапе компиляции, улучшает автодополнение в IDE, повышает читаемость кода и упрощает сопровождение крупных проектов. Vue начиная с версии 3 изначально спроектирован с учётом TypeScript, что делает его использование нативным и удобным.

Ключевая особенность — TypeScript не является обязательным, но его интеграция максимально прозрачна и не требует сложной настройки.


Архитектура Vue 3 и TypeScript

Vue 3 переписан на TypeScript почти полностью. Это повлияло на:

  • строго типизированное API
  • улучшенную систему типов для реактивности
  • точные сигнатуры функций Composition API
  • корректную типизацию шаблонов

Благодаря этому пользовательский код получает максимальную поддержку типов без дополнительной конфигурации.


Использование TypeScript в Single File Components

Single File Component (SFC) поддерживает TypeScript напрямую через атрибут lang="ts".

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  name: 'UserCard'
})
</script>

Компилятор Vue корректно обрабатывает TypeScript-код, а шаблон автоматически получает информацию о типах, определённых в script.


Типизация данных компонента

Options API

При использовании Options API типизация осуществляется через generics и явные аннотации.

data(): { count: number } {
  return {
    count: 0
  }
}

Методы и вычисляемые свойства могут быть типизированы явно, но подход становится громоздким при росте сложности.


Composition API как основной инструмент TypeScript

Composition API предоставляет более естественную интеграцию с TypeScript.

import { ref } from 'vue'

const count = ref<number>(0)

Тип значения внутри ref выводится автоматически, а при необходимости может быть задан явно.

Для reactive используется вывод типов на основе объекта:

const state = reactive({
  name: 'Alice',
  age: 25
})

TypeScript автоматически создаёт тип на основе структуры объекта.


Типизация props

Props типизируются через generics или объектную запись.

import { defineComponent, PropType } from 'vue'

export default defineComponent({
  props: {
    title: {
      type: String,
      required: true
    },
    user: {
      type: Object as PropType<{ id: number; name: string }>,
      required: true
    }
  }
})

В <script setup> типизация становится ещё проще:

defineProps<{
  title: string
  user: {
    id: number
    name: string
  }
}>()

Типизация emits

События также строго типизируются.

defineEmits<{
  (e: 'update', value: number): void
  (e: 'submit'): void
}>()

Это предотвращает передачу неверных аргументов и упрощает поддержку событий.


Работа с шаблонами и типами

Vue автоматически связывает типы из script с шаблоном:

  • переменные из setup доступны с корректными типами
  • props и emits проверяются на этапе разработки
  • ошибки использования методов выявляются до выполнения

Пример ошибки, выявляемой TypeScript:

  • обращение к несуществующему свойству
  • передача строки вместо числа
  • вызов метода с неверным количеством аргументов

Типизация слотов

Слоты могут быть типизированы через интерфейсы:

defineSlots<{
  default(props: { item: string }): any
}>()

Это позволяет контролировать структуру данных, передаваемых в слоты, особенно в библиотечных компонентах.


Типизация provide / inject

При использовании dependency injection рекомендуется выносить ключи в символы с типами:

const UserKey = Symbol() as InjectionKey<User>

provide(UserKey, user)
const user = inject(UserKey)

TypeScript гарантирует соответствие типов между provide и inject.


Работа с внешними типами и API

Vue хорошо сочетается с типами из сторонних библиотек:

  • Axios
  • Pinia
  • Vue Router

Пример с Pinia:

export const useUserStore = defineStore('user', {
  state: () => ({
    id: 0 as number,
    name: '' as string
  })
})

Типы состояния, геттеров и экшенов выводятся автоматически.


Типизация маршрутов

Vue Router поддерживает строгую типизацию параметров маршрутов:

{
  path: '/users/:id',
  name: 'user',
  component: UserView,
  props: route => ({ id: Number(route.params.id) })
}

В компоненте id будет иметь корректный тип.


Типизация асинхронных данных

Асинхронные функции типизируются стандартными средствами TypeScript:

const fetchUser = async (): Promise<User> => {
  const response = await api.get<User>('/user')
  return response.data
}

Это позволяет контролировать структуру данных, получаемых с сервера.


Проверка типов и инструменты

Основные инструменты:

  • vue-tsc — проверка типов SFC
  • Volar — язык-сервер для IDE
  • tsconfig.json — управление строгими режимами

Рекомендуемые настройки:

  • "strict": true
  • "noImplicitAny": true
  • "strictNullChecks": true

Ограничения и особенности

  • TypeScript не выполняется в рантайме
  • шаблоны типизируются на уровне компиляции
  • сложные conditional-типы могут ухудшать читаемость
  • требуется аккуратная работа с any и unknown

Практика типобезопасного проектирования

Основные принципы:

  • минимальное использование any
  • явные интерфейсы для сложных объектов
  • типизация границ системы (API, события, props)
  • вынос общих типов в отдельные файлы
  • использование readonly для неизменяемых данных

TypeScript во Vue.js — не надстройка, а фундаментальная часть современной архитектуры приложений, обеспечивающая надёжность, масштабируемость и предсказуемость поведения кода.