Когда используются union types в TypeScript?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Когда используются union types в TypeScript?
Union types в TypeScript используются для описания переменной или параметра, который может принимать значения нескольких разных типов. Union тип обозначается символом вертикальной черты (|) и позволяет явно указать все возможные типы значения.
Основное определение
Union type — это способ сказать TypeScript: "эта переменная может быть ИЛИ одного типа, ИЛИ другого, ИЛИ третьего".
// Переменная может быть строкой или числом
let id: string | number;
id = 42; // ✅ OK
id = 'user-123'; // ✅ OK
id = true; // ❌ Ошибка: тип boolean не совместим
Когда использовать Union Types
1. Функции с гибкими параметрами
function parseValue(value: string | number): string {
if (typeof value === 'string') {
return value.toUpperCase();
} else {
return value.toString();
}
}
parseValue('hello'); // ✅
parseValue(42); // ✅
parseValue(true); // ❌ Ошибка
2. Возвращаемые значения с ошибками
function fetchUser(id: number): { user: User } | { error: string } {
if (!id) {
return { error: 'Invalid ID' };
}
return { user: { id, name: 'John' } };
}
const result = fetchUser(1);
if ('error' in result) {
console.log('Error:', result.error);
} else {
console.log('User:', result.user);
}
3. Логические состояния в приложении
type LoadingState = 'idle' | 'loading' | 'success' | 'error';
interface DataState {
status: LoadingState;
data?: unknown;
error?: string;
}
const state: DataState = {
status: 'loading',
data: null
};
4. Props компонентов React
interface ButtonProps {
size: 'small' | 'medium' | 'large';
variant: 'primary' | 'secondary' | 'danger';
onClick?: () => void;
}
export const Button: React.FC<ButtonProps> = ({
size,
variant,
onClick
}) => {
return <button className={`btn-${size} btn-${variant}`}>{/* */}</button>;
};
5. Обработка данных разных структур
type ApiResponse =
| { type: 'success'; data: User[] }
| { type: 'error'; code: number; message: string }
| { type: 'loading' };
function handleResponse(response: ApiResponse) {
switch (response.type) {
case 'success':
console.log('Users:', response.data);
break;
case 'error':
console.log(`Error ${response.code}: ${response.message}`);
break;
case 'loading':
console.log('Loading...');
}
}
Type Guards для работы с Union Types
function processInput(value: string | number | boolean) {
// Проверка типа typeof
if (typeof value === 'string') {
console.log('String length:', value.length);
} else if (typeof value === 'number') {
console.log('Number value:', value.toFixed(2));
} else {
console.log('Boolean value:', value);
}
}
// Проверка instanceof
function handleEvent(event: MouseEvent | KeyboardEvent) {
if (event instanceof MouseEvent) {
console.log('Mouse coords:', event.clientX, event.clientY);
} else {
console.log('Key pressed:', event.key);
}
}
// Проверка in (для объектов)
interface Admin { role: 'admin'; permissions: string[] }
interface User { role: 'user'; name: string }
function printRole(user: Admin | User) {
if ('permissions' in user) {
console.log('Admin with permissions:', user.permissions);
} else {
console.log('User:', user.name);
}
}
Discriminated Union (рекомендуемый подход)
Для сложных Union типов используйте discriminated union с общим полем:
type Result<T> =
| { status: 'success'; value: T }
| { status: 'error'; error: Error }
| { status: 'pending' };
function handleResult<T>(result: Result<T>) {
switch (result.status) {
case 'success':
console.log('Success:', result.value);
break;
case 'error':
console.log('Error:', result.error.message);
break;
case 'pending':
console.log('Loading...');
}
}
Union Types vs Any
// ❌ Плохо - используется any
function process(value: any) {
return value.toUpperCase(); // может упасть
}
// ✅ Хорошо - явно указаны типы
function process(value: string | { toString(): string }) {
return typeof value === 'string'
? value.toUpperCase()
: value.toString().toUpperCase();
}
Практические советы
- Предпочитайте Union Types любому значению вместо
any - Используйте discriminated union для сложных сценариев
- Добавляйте type guards для типобезопасности
- Документируйте возможные типы в комментариях
- Используйте narrowing (сужение типов) для безопасности
Union Types — это мощный инструмент TypeScript, который делает код безопаснее и понятнее, предотвращая ошибки на этапе разработки.