✅ Основы типов
Простейшие аннотации, которые помогают избежать ошибок при работе с переменными и данными из API.
let count: number = 0
let title: string = "Hello"
let isActive: boolean = true
let tags: string[] = ["vue", "ts"]
let obj: { id: number; name: string } = { id: 1, name: "Vue" }
Union и literal типы позволяют ограничивать состояние или входные данные.
let state: "loading" | "error" | "success"
let value: number | null
Типы для функций дают уверенность в возвращаемом результате.
function add(a: number, b: number): number {
return a + b
}
✅ Type alias и interface
Это базовые инструменты описания структуры данных.
type — универсальнее, interface — лучше для объектов
type ID = string | number
type ClickHandler = (e: MouseEvent) => void
interface User {
id: ID
name: string
email?: string // необязательно, если может отсутствовать
}
Интерфейсы легко расширяются:
interface Admin extends User {
role: "admin"
}
✅ Enum и const Enum
Enums — удобная альтернатива строковым литералам, особенно если значения используются многократно.
enum Status {
Active,
Disabled
}
const enum Dir {
Up = "UP",
Down = "DOWN"
}
const enum оптимальнее по размеру бандла, но требует поддержки в сборке.
✅ Generics (обобщения)
Нужны, когда тип должен зависеть от входных данных — например, в хукаx, компонентах и сервисах.
function wrap<T>(value: T): T[] {
return [value]
}
const users = wrap<User>({ id: 1, name: "John" })
Generics активно используются под капотом Vue (ref<T>, computed<T>).
✅ Utility Types (очень часто в Vue-продакшене)
Ускоряют типизацию и делают код гибче.
Partial<T>Делает все поля optional
Required<T>Все обязательные
Readonly<T>Запрещает изменять
Pick<T, K>Берёт только указанные поля
Omit<T, K>Удаляет указанные поля
Record<K, T>Типизированные ключи и значения
Пример:
type UserPreview = Pick<User, "id" | "name">
✅ Narrowing (сужение типов)
Обязательный навык при обработке данных из API, где часто приходят unknown | null.
function printId(id: string | number) {
if (typeof id === "string") {
console.log(id.toUpperCase())
} else {
console.log(id.toFixed(2))
}
}
Если TS “сомневается” — проверяй!
✅ Работа с API и Axios
Типизация ответа делает код надёжным и автокомплит более умным.
interface Todo {
id: number
title: string
}
async function getTodos(): Promise<Todo[]> {
const { data } = await axios.get<Todo[]>("/api/todos")
return data
}
✅ Typing props (Composition API)
Типизация пропов избавляет от багов, связанных с неверными входными данными.
const props = defineProps<{
title: string
count?: number
}>()
✅ Typing emits
Позволяет контролировать события: имена и типы передаваемых данных.
const emit = defineEmits<{
(e: "update", value: number): void
}>()
emit("update", 10)
✅ Typing refs и reactive
TS помогает избежать перепутывания типов .value и обычных переменных.
const count = ref<number>(0)
const user = reactive<User>({
id: 1,
name: "John"
})
✅ Computed
Явная типизация нужна, когда TS не может вывести тип сам.
const double = computed<number>(() => count.value * 2)
✅ Typing events & templates
Мышь — MouseEvent, клавиатура — KeyboardEvent, формы — SubmitEvent.
function handleClick(e: MouseEvent) {
console.log(e.clientX)
}
Шаблон:
<button @click="handleClick">Click</button>
✅ Vue Router с типами
Router не всегда знает типы params, поэтому иногда нужен каст:
import { useRoute } from "vue-router"
const route = useRoute()
const id = route.params.id as string
✅ Pinia Store: типизация состояния и действий
TS позволяет точно описать значение state и сигнатуру методов.
export const useUserStore = defineStore("user", {
state: () => ({
user: null as User | null
}),
actions: {
setUser(u: User) {
this.user = u
}
}
})
Vue3.ru