В экосистеме Vue.js utility types играют важную роль, особенно при использовании TypeScript. Они позволяют создавать гибкие, типобезопасные компоненты и облегчать работу с реактивными данными. Рассмотрим ключевые utility types, их применение и тонкости использования в реальных проектах на Vue 3.
Ref и
ReactiveRef<T> используется для хранения
реактивного примитивного значения или объекта. Примитивы, такие как
строки, числа и булевы значения, должны оборачиваться в
ref, чтобы Vue мог отслеживать изменения:
import { ref } from 'vue';
const count = ref(0);
count.value++; // реактивное обновление
Reactive<T> применяется для
создания реактивного объекта целиком:
import { reactive } from 'vue';
const state = reactive({
user: { name: 'Alice', age: 25 },
loggedIn: false
});
state.loggedIn = true; // Vue отследит изменение
Ключевое различие: ref подходит для примитивов и
оберток, reactive — для комплексных объектов.
Readonly и
DeepReadonlyReadonly<T> делает объект или его свойства только
для чтения. Полезно при передаче состояния, которое не должно изменяться
в дочерних компонентах:
import { readonly } from 'vue';
const state = reactive({ count: 0 });
const readonlyState = readonly(state);
readonlyState.count = 10; // ошибка компиляции
DeepReadonly<T> обеспечивает глубокую
неизменяемость всех вложенных свойств, что особенно важно при работе с
большими структурами данных.
Partial и
RequiredPartial<T> превращает все
свойства интерфейса или типа в опциональные, что удобно при обновлении
частей состояния:
interface User {
name: string;
age: number;
}
function updateUser(user: User, updates: Partial<User>) {
Object.assign(user, updates);
}
updateUser({ name: 'Alice', age: 25 }, { age: 26 });
Required<T> наоборот, делает все
свойства обязательными, гарантируя, что объект полностью соответствует
интерфейсу.
Pick и
OmitPick<T, K> выбирает определённые
свойства из типа:
interface User {
id: number;
name: string;
age: number;
}
type UserPreview = Pick<User, 'id' | 'name'>;
Omit<T, K> исключает свойства из
типа, что удобно для создания новых интерфейсов на основе
существующих:
type UserWithoutAge = Omit<User, 'age'>;
Эти utility types помогают управлять структурой данных без дублирования типов.
Extract и
ExcludeExtract<T, U> оставляет только те типы из
T, которые совместимы с U.
Exclude<T, U> удаляет из T все типы,
совместимые с U.
type T = string | number | boolean;
type OnlyStr ing = Extract<T, string>; // string
type NotBoolean = Exclude<T, boolean>; // string | number
В Vue это удобно при работе с ограниченными наборами значений, например, для пропсов компонентов.
ReturnType и
ParametersReturnType<T> позволяет получить тип возвращаемого
значения функции:
function getUser() {
return { name: 'Alice', age: 25 };
}
type UserType = ReturnType<typeof getUser>;
Parameters<T> возвращает тип параметров функции в
виде кортежа, что полезно для типизации коллбеков:
function setUser(name: string, age: number) {}
type SetUserParams = Parameters<typeof setUser>; // [string, number]
В контексте Vue это особенно полезно для composition API и фабрик функций.
NonNullable и
AwaitedNonNullable<T> исключает
null и undefined из типа:
type MaybeString = string | null | undefined;
type DefinitelyString = NonNullable<MaybeString>; // string
Awaited<T> извлекает тип
результата промиса:
type Response = Promise<{ data: string }>;
type DataType = Awaited<Response>; // { data: string }
Эти utility types помогают избежать ошибок, связанных с неопределёнными или асинхронными значениями в компонентах Vue.
При работе с setup() часто требуется строгая
типизация:
import { ref, computed } from 'vue';
interface Product {
name: string;
price: number;
discount?: number;
}
const product = ref<Product>({ name: 'Book', price: 100 });
const finalPrice = computed(() => product.value.price * (1 - (product.value.discount ?? 0)));
Использование utility types позволяет точно описывать структуру реактивных данных, их изменение и вычисляемые свойства.
readonly для пропсов, чтобы
предотвратить их изменение внутри компонентов.Partial и Omit упрощают работу с формами и
объектами обновления.ReturnType и Parameters помогают избегать
дублирования интерфейсов для функций внутри composables.Ref, Reactive и utility types
позволяет полностью контролировать типизацию реактивного состояния.Utility types в Vue.js создают мощный инструментарий для безопасного и предсказуемого управления состоянием и компонентами. Их использование значительно снижает вероятность ошибок, облегчает поддержку кода и делает проект более масштабируемым.