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

Как вывести тип из нетипизированного JSON-объекта?

3.0 Senior🔥 101 комментариев
#JavaScript Core#TypeScript

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

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

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

Как вывести тип из нетипизированного JSON-объекта

Вывод типов (Type Inference) - это мощная возможность TypeScript, которая позволяет автоматически определять типы переменных на основе их значений. Это особенно полезно при работе с JSON, когда структура известна заранее.

1. Базовый вывод типов

TypeScript автоматически определяет типы литералов:

const user = {
  id: 1,
  name: 'John',
  email: 'john@example.com',
  active: true
};

// TypeScript выводит тип автоматически:
// const user: {
//   id: number;
//   name: string;
//   email: string;
//   active: boolean;
// }

2. Оператор typeof для извлечения типа

const jsonData = {
  title: 'Frontend',
  level: 'advanced',
  score: 95
};

// Извлекаем тип из объекта
type Course = typeof jsonData;

// Теперь можем использовать Course как тип
const course: Course = {
  title: 'React',
  level: 'intermediate',
  score: 88
};

3. Использование JSON.parse с типизацией

const jsonString = '{"id": 1, "name": "Alice"}';

// Неправильно - type any
const data: any = JSON.parse(jsonString);

// Правильно - определяем ожидаемый тип
interface User {
  id: number;
  name: string;
}

const user: User = JSON.parse(jsonString);

4. Вывод типов из массивов

const users = [
  { id: 1, name: 'John', role: 'admin' },
  { id: 2, name: 'Jane', role: 'user' },
  { id: 3, name: 'Bob', role: 'user' }
];

// Извлекаем тип элемента массива
type User = typeof users[number];

// User теперь имеет тип:
// {
//   id: number;
//   name: string;
//   role: string;
// }

const newUser: User = { id: 4, name: 'Alice', role: 'admin' };

5. Оператор keyof для получения ключей

const config = {
  apiUrl: 'https://api.example.com',
  timeout: 5000,
  retries: 3
};

// Получаем тип всех возможных ключей
type ConfigKey = keyof typeof config;
// 'apiUrl' | 'timeout' | 'retries'

function getConfig(key: ConfigKey) {
  return config[key];
}

getConfig('apiUrl'); // OK
getConfig('invalid'); // Error

6. Утилита as const для литеральных типов

// Без as const - типы расширяются
const color = 'red'; // type: string

// С as const - сохраняются литеральные типы
const color2 = 'red' as const; // type: 'red'

const theme = {
  primary: '#FF5733',
  secondary: '#33FF57',
  dark: '#333333'
} as const;

type ThemeColor = typeof theme[keyof typeof theme];
// '#FF5733' | '#33FF57' | '#333333'

7. Оператор Partial для опциональных полей

const user = {
  id: 1,
  name: 'John',
  email: 'john@example.com'
};

type UserType = typeof user;

// Сделаем все поля опциональными
type PartialUser = Partial<UserType>;

const update: PartialUser = {
  email: 'new@example.com'
  // id и name опциональны
};

8. Оператор Pick для выбранных полей

const product = {
  id: 1,
  name: 'Laptop',
  price: 1000,
  stock: 5,
  description: 'High-end laptop'
};

type ProductType = typeof product;

// Берём только нужные поля
type ProductSummary = Pick<ProductType, 'id' | 'name' | 'price'>;

const summary: ProductSummary = {
  id: 1,
  name: 'Laptop',
  price: 1000
};

9. Оператор Record для типизации объектов

// Определяем ключи
type Language = 'en' | 'es' | 'fr';

// Record автоматически типизирует объект с этими ключами
const translations: Record<Language, string> = {
  en: 'Hello',
  es: 'Hola',
  fr: 'Bonjour'
};

// Будет ошибка:
const bad: Record<Language, string> = {
  en: 'Hello',
  es: 'Hola'
  // Ошибка: отсутствует 'fr'
};

10. Вывод типов из fetch запросов

interface ApiResponse<T> {
  data: T;
  status: number;
}

async function fetchUser(id: number) {
  const response = await fetch(`/api/users/${id}`);
  const data: ApiResponse<typeof user> = await response.json();
  return data;
}

// Или с автоматическим выводом
const fetchData = async <T>(url: string): Promise<T> => {
  const response = await fetch(url);
  return response.json();
};

const userData = await fetchData<typeof user>('/api/user');

11. Утилиты TypeScript для вывода типов

// ReturnType - тип возвращаемого значения функции
function getUser() {
  return { id: 1, name: 'John' };
}

type User = ReturnType<typeof getUser>;

// Parameters - типы параметров функции
function process(id: number, name: string) {}
type ProcessParams = Parameters<typeof process>;
// [id: number, name: string]

// InstanceType - тип экземпляра класса
class UserService {
  getData() {}
}

type ServiceInstance = InstanceType<typeof UserService>;

12. Практический пример с API

// Получаем JSON от API
const apiResponse = {
  id: '123',
  username: 'johndoe',
  email: 'john@example.com',
  profile: {
    bio: 'Frontend developer',
    avatar: 'https://example.com/avatar.jpg'
  }
};

// Выводим тип из реального объекта
type User = typeof apiResponse;

// Или создаём интерфейс для переиспользования
interface UserFromAPI extends typeof apiResponse {}

// Используем в компоненте React
function UserCard({ user }: { user: User }) {
  return (
    <div>
      <h1>{user.username}</h1>
      <p>{user.profile.bio}</p>
    </div>
  );
}

Best Practices

  • Используйте typeof для извлечения типов из объектов
  • Применяйте as const для литеральных типов
  • Используйте keyof для безопасного доступа к ключам
  • Предпочитайте интерфейсы для API контрактов
  • Используйте утилиты типов (Partial, Pick, Record)

Выводы

TypeScript позволяет вывести типы из JSON-объектов несколькими способами. Выбор метода зависит от контекста - для простых объектов используй typeof, для более сложных структур создавай интерфейсы.