Avatar ·

Ошибка импорта SVG файлов в TypeScript: Cannot find module или неверный тип

Всем привет! Я новичок в TypeScript и столкнулся с проблемой при попытке импортировать SVG-файлы в React-проект. У меня есть компонент иконки: ```typescript import React from 'react'; import { ReactComponent as Logo } from './logo.svg'; const Header: React.FC = () => { return (
); }; export default Header; ``` Но TypeScript выдаёт ошибку: `Cannot find module './logo.svg' or its corresponding type declarations.` Я проверил — файл существует, путь правильный. Если использую `require('./logo.svg')`, то получаю `any` тип, и это тоже неудовлетворительно. Мой `tsconfig.json` выглядит так: ```json { "compilerOptions": { "target": "ES5", "module": "ESNext", "strict": true, "jsx": "react-jsx", "moduleResolution": "node", "esModuleInterop": true }, "include": ["src"] } ``` Я использую Create React App, но с TypeScript шаблоном. Всё остальное работает нормально, но SVG файлы не импортируются. Пробовал перезагружать IDE, удалять node_modules и ставить заново — не помогает. Как правильно настроить TypeScript, чтобы он понимал SVG файлы? И как сделать так, чтобы импорт работал и как React-компонент, и как URL для src атрибута? Буду благодарен за подробное объяснение. Спасибо! <<>>

Причина проблемы

TypeScript по умолчанию не знает, что такое SVG-файлы. Он умеет импортировать только .ts, .tsx, .js, .jsx, .d.ts и другие стандартные расширения. Когда вы пишете import Logo from './logo.svg', компилятор ищет модуль с таким именем, но не находит его, потому что для .svg нет объявлений типов (type declarations).

Решение: создание декларации модуля (declaration file)

Вам нужно объявить TypeScript, что SVG-файлы — это валидные модули. Для этого создайте файл src/custom.d.ts (или src/declarations.d.ts) со следующим содержимым:

// src/custom.d.ts
declare module '*.svg' {
  import React = require('react');
  export const ReactComponent: React.FC<React.SVGProps<SVGSVGElement>>;
  const src: string;
  export default src;
}

Объяснение кода

  • declare module '*.svg' — говорит TypeScript: "любой файл, который заканчивается на .svg, обрабатывай как модуль с этими экспортами".
  • ReactComponent — это именованный экспорт, который используется в синтаксисе import { ReactComponent as Logo } from './logo.svg'. Мы типизируем его как функциональный компонент React, принимающий стандартные SVG-пропсы.
  • export default src: string — это для случая, когда вы импортируете SVG как URL: import logoSrc from './logo.svg'. Тип string подходит, потому что в результате вы получите строку с путём к файлу (например, /static/media/logo.abc123.svg).

Проверка и использование

После добавления этого файла перезапустите вашу IDE (или просто перезагрузите TypeScript сервер в VS Code через Ctrl+Shift+P → "TypeScript: Restart TS server"). Теперь оба варианта импорта будут работать без ошибок:

// Вариант 1: как React-компонент
import { ReactComponent as Logo } from './logo.svg';
<Logo width={50} height={50} />

// Вариант 2: как URL для src
import logoSrc from './logo.svg';
<img src={logoSrc} alt="Logo" />

Если вы используете Create React App (CRA)

В CRA с TypeScript шаблоном обычно уже есть файл react-app-env.d.ts. Если он есть — просто добавьте туда объявление модуля для SVG. Если нет — создайте. CRA сам обрабатывает SVG через Webpack (с помощью @svgr/webpack и file-loader), поэтому декларация типов — это единственное, что нужно добавить.

Дополнительные советы

  • Убедитесь, что файл custom.d.ts находится в папке, которая включена в include в вашем tsconfig.json (по умолчанию это src).
  • Если вы используете Vite, Next.js или другой фреймворк — проверьте их документацию. Например, в Vite SVG импорт работает из коробки, но типы нужно объявлять отдельно.
  • Не забудьте удалить require('./logo.svg'), если он у вас остался — он не даёт корректной типизации.

После этих шагов ошибка Cannot find module исчезнет, и вы сможете использовать SVG как настоящие React-компоненты с полной поддержкой типов.

<<>>

Альтернативный подход: использование библиотеки @types

Если вы не хотите вручную создавать декларации, можно установить пакет @types/webpack-env (если вы используете Webpack, как в CRA) или @types/node, которые иногда включают базовые типы для импорта файлов. Однако это не всегда решает проблему со SVG, так как типы для SVG-компонентов там отсутствуют.

Для проектов на Vite

В Vite SVG импорт работает иначе. Вам нужно установить плагин vite-plugin-svgr и добавить его в конфигурацию. После этого создайте файл src/vite-env.d.ts с таким содержимым:

/// <reference types="vite/client" />
declare module '*.svg' {
  import React from 'react';
  const SVGComponent: React.FC<React.SVGProps<SVGSVGElement>>;
  export default SVGComponent;
}

Для Next.js

В Next.js 13+ SVG импорт без дополнительных настроек не работает. Рекомендуется использовать next-image для статических SVG или пакет @svgr/webpack с настройкой в next.config.js. Типы объявляются аналогично — через custom.d.ts.

Краткий итог

Самый универсальный и простой способ — создать файл декларации. Он работает в любом окружении (CRA, Vite, Next.js, Webpack, Rollup) и не требует установки дополнительных зависимостей. Второй вариант — использовать специфичные для сборщика плагины, но это усложняет конфигурацию.