在TypeScript React中导入图片 - "找不到模块"

218

我正在尝试在使用TypeScript的React组件中导入图像。我使用的打包工具是Parcel(而不是Webpack)。

我在项目中创建了一个带有图像文件扩展名的 .d.ts 文件,并将其包含在 tsconfig.json 中。但是,当我尝试导入图像时,TS会抱怨找不到模块。

我的项目结构:

+ src
  + assets
    - image.jpg
  + components
    - Box.tsx
    - App.tsx
  - index.d.ts
  - index.html
  - index.tsx
- tsconfig.json
- tslint.json

我尝试像这样在 App.tsx 中导入图像。VS Code下划线标记了 '../assets/image.jpg',并显示了 无法找到模块'../assets/image.jpg'

import * as React from 'react';
import * as img from '../assets/image.jpg';

const Box = props => {
  // do things...
}

export default Box;

我在网上找到的讨论指出需要自己定义一个.d.ts文件,因此我创建了这个带有以下代码行的index.d.ts文件。

declare module '*.jpg';

然后在 "compilerOptions" : {...} 后面的 tsconfig.json 中添加 "include": ["./src/index.d.ts"]

我错过了什么?我该如何解决 TS 抛出的错误?


请查看 https://github.com/Microsoft/TypeScript/issues/15146。 - diegosasw
你可以像这样做 https://dev59.com/wFcP5IYBdhLWcg3w6-EH#66251201 - Carlos
有没有任何@types包可以直接提供这些声明,这样我就不必自己明确地提供它们了? - Paul Razvan Berg
有没有任何@types包可以直接提供这些声明,这样我就不必自己明确地提供它们了? - undefined
20个回答

256
创建src文件夹中的index.d.ts文件,并添加此行。
declare module '*.jpg';

33
可以工作,但您能否为我解释一下为什么以及如何工作?这与 TypeScript 有关吗,还是与 VS Code 有关?这是否类似于忽略所有 linting 问题中的错误?请澄清。谢谢。 - Rishav
@Rishav 我认为这是一种特定的速记声明 https://www.typescriptlang.org/docs/handbook/modules.html 从速记模块导入的所有内容都将具有任何类型。 - llamerr
3
很奇怪的是,如果我在 VS Code 中关闭 index.d.ts 文件,错误就会再次出现。只有当这个文件被打开时才能正常工作。有人知道为什么吗? - loekTheDreamer
1
@loekTheDreamer 我也遇到了类似的问题,如果我直接在文件中引用,即放置 /// <reference path="../../index.d.ts" />,就会出现错误。 - Abuw

155
如果您在tsconfig.json中写入了"include": ["./src/index.d.ts"],而且没有"files"设置,则表示由tsconfig.json定义的项目仅包括单个文件./src/index.d.ts。当您在VS Code中打开任何其他文件时,VS Code会使用一个独立的语言服务实例,不使用您的tsconfig.json。调整您的"include"设置以匹配项目中的所有.ts.tsx文件,或者只需删除它并依赖于包含tsconfig.json目录下的所有文件的默认行为。

Round 2

TypeScript正在忽略index.d.ts,因为它假设index.d.ts是从index.tsx生成的,并且index.tsx更可能是最新的。将您的index.d.ts文件命名为其他名称,例如declaration.d.ts

2
我确实字面上写了 "include": ["./src/index.d.ts"]。现在我已经删除了那行并重新启动了 VS Code,但问题仍然存在(无法找到模块 '../assets/image.jpg')。问题可能是由打包工具引起的吗?但是如果 VS Code 使用单独的语言服务,我认为使用哪个打包工具并不重要。 - John
3
没关系,我想我找到了问题所在。请查看更新后的答案。 - Matt McCutchen
3
哇,这真是太神奇了,非常感谢!!我几乎整个上午都在尝试弄清楚为什么它不起作用:))) - John
4
你的第二轮回答真是一份厚礼,你解决了我在 index.d.ts 和 SVG 上的问题,非常感谢! - JesDaw
第二轮面试,如果我们有机会见面,午餐我请客。非常感谢! - Naser Mohd Baig
第二轮也很顺利。好东西。 - travelerrrrrrr

113
创建模块/类型
# src/types/images.d.ts
declare module '*.jpg';
declare module '*.jpeg';

修改 tsconfig.json 文件

{
    "compilerOptions": {
        "typeRoots" : ["node_modules/@types", "src/types"]
    }
}

嗨,我想深入了解一下,因为我已经创建了types/images.d.ts文件,但是typeRoots选项没有起作用,然而在include中使用相同的声明“src/types”却可以工作。现在我的include看起来像这样:“include”: [“src/*”,“src/types”],这有点像重复路径,因为src/*也应该覆盖第二个用例,但它并没有。为什么include可以工作而typeRoots不能呢?因为“'typeRoots'指定编译器应查找类型定义的根文件夹”。 - seven
4
我不需要修改typeRoots,只需将d.ts文件放入项目中即可。 - Tamir Daniely

41

解决这个问题可以有很多方法。

解决方案1:
使用require来包含图像

<img src={require('../../assets/logo.png')} alt="" />

解决方案 #2:

不要使用import导入图片,改为使用constrequire导入,例如:

const logo = require("../../assets/logo.png");

然后像这样使用它:

<img src={logo} alt="" />

解决方案 #3:
在你的src文件夹中有一个react-app-env.d.ts文件。 如果你没有看到它,请在src文件夹中创建一个名为react-app-env.d.ts的新文件。

现在在你的react-app-env.d.ts文件中,添加以下代码。

declare module "*.png";
declare module "*.svg";
declare module "*.jpeg";
declare module "*.jpg";

解决方法 #4:
在您的 src 文件夹中创建 declaration.d.ts
然后在其中添加以下文本。

declare module "*.png";
declare module "*.svg";
declare module "*.jpeg";
declare module "*.jpg";

现在你需要让你的tsconfig.json看起来像这样:

{
  "compilerOptions": {},
  "include": [
    "src",
    "src/declaration.d.ts",
  ]
}

这里输入图片描述


解决方案 #5:

在你的src文件夹中创建一个types文件夹,并在其中添加images.d.ts文件。 将以下文本添加到该文件中。

declare module "*.png";
declare module "*.svg";
declare module "*.jpeg";
declare module "*.jpg";

现在按照这样的方式配置tsconfig.json:

{
  "compilerOptions": {
    "typeRoots": [
      "node_modules/@types",
      "src/types"
    ],
}

这里输入图片描述



const logo = require("../../assets/logo.png")import logo from "../../assets/logo.png" 会产生相同的错误。在发布内容前,请先进行测试。 - Peter Schorn
它对我起作用,这就是我在这里发布它的原因,而且你可以清楚地看到我得到了积分,这意味着它帮助了其他人。如果它不起作用,请尝试另一个解决方案,简单 :) - Mohammad Ayoub Khan
我使用了解决方案#4,在我的React Native项目中运行良好。谢谢。 - Dholu

26

针对使用 Typescript 的 "react": "^18.2.0",请执行以下操作:

  1. 在您的 src/ 目录中创建一个名为 declaration.d.ts 的文件。
  2. 添加以下代码行:

declare module "*.jpg"
declare module "*.png"

就是这样,错误应该已经消失了。

祝你好运!


你能详细解释一下这个做了什么吗? - Manoj
好的,它的作用是告诉 TypeScript 处理器该扩展名的任何文件都被认为是模块,并且可以从项目中的任何位置导入。最初,如果您将其导入到 TypeScript 程序中时,TypeScript 处理器将会警告您找不到文件扩展名。因此,有了这个声明,那条红线就会消失。 - ObiTech Invents
对我没有起作用,也许是因为单一仓库或者我使用的是 Vite? - Kasir Barati
我猜那应该就是原因了。 - ObiTech Invents
@ObiTechInvents 有解决这个问题的想法吗? - Kasir Barati
1
@KasirBarati,对我真正起作用的是在src文件夹的根目录下创建了一个名为declaration.d.ts的文件,并添加了上述代码行,然后停止本地服务器并重新启动。如果这对您没有起作用,可以尝试创建一个名为types.d.ts的文件,然后重复相同的方法。祝好运! - ObiTech Invents

24

这花了我大约一个小时,所以我会分享解决方案。

Matt McCutchen的解决方案在某种程度上对我有用,但是我仍然面临着VSCode错误。为了解决这个问题,我将我的tsconfig.json和index.d.ts移动到根目录,而不是src目录下。现在你的tsconfig.json应该像这样:

"include": ["src", "index.d.ts"]

对于您的index.d.ts,这样做:

declare module '*.png';
declare module '*.jpg';

(^ 根据您的打字需求进行微调)


3
为了解决这个问题,我把 index.d.ts 文件从 src 目录移动到根目录。这也是我的问题所在。谢谢! - GG.
1
我尝试了使用“require('./image/location.jpg')”的解决方案,以及在根目录中创建index.d.ts并在tsconfig.json中更新包含内容的解决方案,两者都对我有效。 - James F. Thomas
1
请检查您的图像类型扩展名是否大写,因此请添加以下声明: declare module '.png'; declare module '.PNG'; - nativelectronic
对我来说,这似乎一开始是有效的,但迟早会再次出现“模块未找到”的错误。我认为这是parcel中的一个bug,我们不应该需要解决方法或长时间的讨论来加载图像这样基本的事情! - Kokodoko

23

有一个解决方法, 例如,

import logo from "../../assets/logo.png"

将此更改为

const logo =  require("../../assets/logo.png")

12
会出现类似于“require语句不是导入语句的一部分”的错误。 - Jyothu
安装 requireJS (还是 CommonJS) - tjvg1991
2
如果您正在使用 react < 17.0.1 版本,那么请使用 require;如果您使用的是 17.0.1 及以上版本,则请使用 import。 - Andrija Gajic

8
当你使用create-react-app时,应该有一个名为"react-app-env.d.ts"的文件。这个文件将所有类型的图像文件和其他许多文件定义为可以导入的模块。文件内应包含以下内容:
/// <reference types="react-scripts" />

5

我声明了多个图像类型,并且必须将它们放在单独的 .d.ts 文件中,以使 VS Code 不报错:

src/types/image.jpg.d.ts:

declare module '*.jpg' {
  import { ImageSourcePropType } from 'react-native'

  const content: ImageSourcePropType

  export default content
}

src/types/image.png.d.ts:

declare module '*.png' {
  import { ImageSourcePropType } from 'react-native'

  const content: ImageSourcePropType

  export default content
}

src/types/image.svg.d.ts:

declare module '*.svg' {
  import React from 'react'
  import { SvgProps } from 'react-native-svg'

  const content: React.FC<SvgProps>

  export default content
}

无需对tsconfig等进行任何调整。


谢谢,这也让phpStorm感到高兴。 - pino

4
我已经复制粘贴了:
/// <reference types="react-scripts" />

从我以前的项目中,react-app-env.d.ts 此文件是有效的。

在最新版本的 CRA(当选择语言使用 TS 时),此文件会被自动添加到源代码文件夹,并包含如上所示的单行指令。它是用于引用来自 react-scripts 的类型的指示。


2
这两行是注释吗? - Akber Iqbal
3
它们不仅仅是注释。就JavaScript而言,它们确实是注释。但是,第一行是一个指令,告诉eslint忽略下一行的代码规范检查。在代码规范检查之前,eslint会寻找这些类型的注释。第二行是引用TypeScript文件中类型的方式。请参见->https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html - Dmase05
抑制错误并不能解决潜在问题,这是一种糟糕的做法! - Michael Eakins
@MichaelEakins 第二行实际上是清除错误,而不是像你所建议的那样抑制它。第一行对于这个问题描述来说几乎没有用处。 - SmartE
在新的 React TypeScript 安装中,该文件已经包含在其中。我不小心删除了这个文件。非常感谢。 - nalendro16

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接