Avatar ·

Как правильно импортировать JSON файл в TypeScript? Ошибка при импорте

Всем привет! Я новичок в TypeScript и столкнулся с проблемой при попытке импортировать JSON файл в свой проект. У меня есть файл `config.json`, который лежит в корне проекта: ```json { "apiUrl": "https://api.example.com", "port": 3000, "debug": true } ``` Я пытаюсь импортировать его в TypeScript файле `app.ts`: ```typescript import config from './config.json'; console.log(config.apiUrl); ``` Но получаю ошибку от TypeScript компилятора: `Cannot find module './config.json'. Consider using '--resolveJsonModule' to import module with '.json' extension.` Я уже пробовал: 1. Добавить `"resolveJsonModule": true` в tsconfig.json — не помогло. 2. Использовать `import * as config from './config.json'` — та же ошибка. 3. Переместить JSON файл в другую папку — без изменений. Подскажите, пожалуйста, как правильно импортировать JSON в TypeScript? Может быть, нужно что-то дополнительно настроить или есть другой способ читать JSON файлы? Буду благодарен за подробное объяснение! Использую TypeScript версии 4.9.5, Node.js 18.16.0. Проект без фреймворка, просто TypeScript + Node. <<>>

Пошаговое решение проблемы импорта JSON в TypeScript

Ошибка, которую вы получаете, связана с тем, что по умолчанию TypeScript не умеет импортировать JSON файлы. Это сделано по соображениям безопасности и типизации. Однако есть несколько способов решить эту проблему. Рассмотрим самый правильный и популярный.

Способ 1: Включение resolveJsonModule (рекомендуемый)

Это самый простой и правильный способ. Добавьте в ваш tsconfig.json две опции:

{
  "compilerOptions": {
    "resolveJsonModule": true,
    "esModuleInterop": true,
    // ... остальные настройки
  }
}

Важно: esModuleInterop нужен для корректной работы импорта по умолчанию (import config from './config.json'). Без него придётся использовать import * as config from './config.json'.

После добавления этих настроек перезапустите компилятор или ваш редактор кода (VS Code). Теперь импорт будет работать:

import config from './config.json';

console.log(config.apiUrl);  // "https://api.example.com"
console.log(config.port);    // 3000
console.log(config.debug);   // true

TypeScript автоматически выведет типы из JSON. Например, config.apiUrl будет иметь тип string, config.port — number, config.debug — boolean.

Способ 2: Явное объявление модуля (для сложных случаев)

Если по каким-то причинам вы не можете использовать resolveJsonModule, можно объявить модуль для JSON файлов вручную. Создайте файл json.d.ts (или declarations.d.ts) в корне проекта:

declare module "*.json" {
  const value: any;
  export default value;
}

Но этот способ менее предпочтителен, так как теряется типизация (все поля будут any).

Способ 3: Чтение через fs (для Node.js)

Если вы работаете в среде Node.js, можно прочитать JSON файл через модуль fs:

import * as fs from 'fs';
import * as path from 'path';

const configPath = path.join(__dirname, 'config.json');
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));

console.log(config.apiUrl);

Этот способ даёт полный контроль, но требует больше кода и не даёт статической типизации без дополнительных усилий.

Важные замечания

  • Пути: JSON файл должен быть в той же директории или путь должен быть указан относительно файла, из которого импортируете.
  • Кэширование: При использовании resolveJsonModule JSON импортируется как модуль, поэтому изменения в JSON файле потребуют перезапуска компилятора (в dev режиме — перезагрузки через ts-node --watch или nodemon).
  • Большие файлы: Для больших JSON файлов (например, базы данных) лучше использовать fs с асинхронным чтением, чтобы не блокировать поток.

Рекомендую использовать первый способ (resolveJsonModule), так как он наиболее идиоматичен для TypeScript и сохраняет типизацию.

<<>>

Альтернативный подход: создание TypeScript конфигурационного файла

Если вам нужно импортировать конфигурацию, возможно, стоит задуматься о том, чтобы хранить её в TypeScript файле вместо JSON. Это даёт несколько преимуществ:

// config.ts
export const config = {
  apiUrl: "https://api.example.com",
  port: 3000,
  debug: true
} as const;  // as const для строгой типизации

Тогда импорт будет работать без каких-либо дополнительных настроек:

import { config } from './config';

console.log(config.apiUrl);  // тип string
console.log(config.port);    // тип number (точнее, литеральный тип 3000)

Преимущества:

  • Не нужно настраивать resolveJsonModule
  • Полная типизация с возможностью использования TypeScript фич (enum, интерфейсы, вычисляемые значения)
  • Можно использовать комментарии и логику
  • Поддержка рефакторинга и автодополнения в IDE

Недостатки:

  • Нельзя использовать в проектах, где конфигурация должна быть в чистом JSON (например, для внешних сервисов)
  • Требует компиляции TypeScript в JavaScript перед использованием

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