← Назад к вопросам

Как понять, какой тип пришёл с Backend?

2.0 Middle🔥 111 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Определение типов данных с Backend

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

Способ 1: Посмотреть в DevTools

// В консоли браузера
fetch('/api/users/123')
  .then(r => r.json())
  .then(data => {
    console.log(data); // Видишь структуру
    console.log(typeof data); // object
    console.log(Array.isArray(data)); // true/false
    
    // Проверка конкретного поля
    if (data.user) {
      console.log(typeof data.user); // object
      console.log(data.user.name); // видишь значение и тип
    }
  });

// РЕЗУЛЬТАТ в консоли:
// {
//   "id": "123e4567-e89b-12d3-a456-426614174000",  <- string (UUID)
//   "name": "John",                                 <- string
//   "age": 30,                                      <- number
//   "isActive": true,                               <- boolean
//   "emails": ["john@example.com"],                 <- array of strings
//   "metadata": {                                   <- nested object
//     "createdAt": "2024-01-15T10:30:00Z",         <- string (ISO date)
//     "tags": ["admin", "user"]                     <- array of strings
//   }
// }

Способ 2: Использовать Network tab

Chrome DevTools -> Network -> XHR -> выбрать запрос -> Response tab

Там видишь полный JSON ответ со всеми типами.

Способ 3: Проверить документацию API

// Документация обычно описывает эту структуру
// GET /api/users/{id}
// Response 200:
// {
//   "id": string (UUID)
//   "name": string
//   "email": string
//   "age": number (integer)
//   "isActive": boolean
//   "roles": string[] (array of role names)
//   "createdAt": string (ISO 8601 datetime)
//   "metadata": {
//     "lastLogin": string | null
//     "loginCount": number
//   }
// }

Инструменты для определения типов

// 1. Console inspection
const data = { name: 'John', age: 30 };
Object.entries(data).forEach(([key, value]) => {
  console.log(`${key}: ${typeof value}`);
});
// Output:
// name: string
// age: number

// 2. JSON.stringify для видения структуры
const complex = {
  user: { name: 'John' },
  scores: [1, 2, 3],
  date: new Date().toISOString(),
};
console.log(JSON.stringify(complex, null, 2));

// 3. Object.keys() для просмотра полей
const response = await api.get('/users/123');
console.log(Object.keys(response)); 
// ['id', 'name', 'email', 'age', 'isActive', 'roles', 'metadata']

// 4. instanceof для проверки типов
if (response.date instanceof Date) {
  console.log('Date object');
} else {
  console.log('String, нужно преобразовать');
}

Генерирование TypeScript типов из JSON

// Способ 1: Вручную через интерпретацию
// Глядя на JSON ответ:
interface UserResponse {
  id: string;          // UUID string
  name: string;
  email: string;
  age: number;
  isActive: boolean;
  roles: string[];
  createdAt: string;   // ISO 8601 string
  metadata?: {
    lastLogin: string | null;
    loginCount: number;
  };
}

// Способ 2: Использовать инструменты
// https://app.quicktype.io/ - paste JSON -> получи TypeScript типы

// Способ 3: Использовать Zod для валидации И типов
import { z } from 'zod';

const UserSchema = z.object({
  id: z.string().uuid(),
  name: z.string(),
  email: z.string().email(),
  age: z.number().int().positive(),
  isActive: z.boolean(),
  roles: z.array(z.string()),
  createdAt: z.string().datetime(),
  metadata: z.object({
    lastLogin: z.string().datetime().nullable(),
    loginCount: z.number().int().nonnegative(),
  }).optional(),
});

type User = z.infer<typeof UserSchema>;

// Использование с валидацией
const response = await api.get('/users/123');
try {
  const user = UserSchema.parse(response);
  // user имеет тип User и гарантированно валиден
} catch (error) {
  console.error('Invalid response:', error);
}

Особые типы данных с backend

// 1. Dates - обычно приходят как ISO strings
// JSON: "createdAt": "2024-01-15T10:30:00.000Z"
// Type: string, но нужно преобразовать в Date

interface Event {
  date: string; // На фронте типизируем как string
}

const event = await fetchEvent();
const jsDate = new Date(event.date); // Преобразуем в Date

// 2. UUIDs - строки, но с определённым форматом
// Type: string, но валиден только UUID v4 формат
interface Resource {
  id: string; // UUID
}

// 3. Enums - могут приходить как строки или числа
// Backend может прислать:
// { "status": "active" } или { "status": 1 }

enum Status {
  Active = 'active',
  Inactive = 'inactive',
  Pending = 'pending',
}

interface User {
  status: keyof typeof Status; // 'active' | 'inactive' | 'pending'
}

// 4. Nullable поля
// { "email": "user@example.com" } или { "email": null }

interface Profile {
  email: string | null;
  phone?: string; // Может отсутствовать
  nickname: string | undefined; // Может быть undefined
}

// 5. Arrays с конкретными типами
// { "tags": ["admin", "user", "moderator"] }

interface User {
  tags: string[];
  scores: number[];
  permissions: ('read' | 'write' | 'delete')[];
}

// 6. Unions - несколько возможных типов
// { "value": "text" } или { "value": 123 }

interface Response {
  value: string | number;
}

Полный пример: API ответ и типы

// API ОТВЕТ (JSON из network tab):
{
  "ok": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "John Doe",
    "email": "john@example.com",
    "role": "admin",
    "avatar": "https://example.com/avatar.jpg",
    "stats": {
      "posts": 42,
      "followers": 1520,
      "following": 320,
      "verified": true
    },
    "friends": [
      { "id": "id1", "name": "Alice" },
      { "id": "id2", "name": "Bob" }
    ],
    "lastSeen": "2024-01-15T14:30:00Z",
    "preferences": {
      "theme": "dark",
      "notifications": true,
      "language": "en",
      "customFields": null
    }
  },
  "timestamp": "2024-01-15T14:35:22Z"
}

// ТИПЫ для этого ответа:
interface FriendInfo {
  id: string;
  name: string;
}

interface UserStats {
  posts: number;
  followers: number;
  following: number;
  verified: boolean;
}

interface Preferences {
  theme: 'light' | 'dark';
  notifications: boolean;
  language: string;
  customFields: null | Record<string, any>;
}

interface UserData {
  id: string;
  name: string;
  email: string;
  role: 'admin' | 'user' | 'moderator';
  avatar: string;
  stats: UserStats;
  friends: FriendInfo[];
  lastSeen: string; // ISO 8601 datetime
  preferences: Preferences;
}

interface ApiResponse<T> {
  ok: boolean;
  data: T;
  timestamp: string;
}

type GetUserResponse = ApiResponse<UserData>;

// ИСПОЛЬЗОВАНИЕ:
const response: GetUserResponse = await api.get('/users/123');
console.log(response.data.name); // TypeScript знает это string
console.log(response.data.stats.posts); // TypeScript знает это number

Контрольный список

  • Посмотрел в DevTools Network tab -> Response
  • Определил все поля и их типы
  • Заметил nullable/optional поля (null, undefined)
  • Определил типы для вложенных объектов
  • Определил типы для array элементов
  • Проверил наличие enum/literal types
  • Заметил date fields и решил как их типизировать
  • Создал интерфейсы для структур
  • Используешь Zod для валидации если критично

Правильная типизация данных с backend - это основа безопасности и удобства разработки в TypeScript.

Как понять, какой тип пришёл с Backend? | PrepBro