203

I am trying to import images to use inside a React component with TypeScript. The bundler I'm using is Parcel (not Webpack).

I have created a .d.ts file inside the project with the image file extension, and included it inside tsconfig.json. However, when I try to import an image, TS yells at me about Cannot find module.

My project structure:

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

I tried to import the image in App.tsx like this. VS Code underlined '../assets/image.jpg' and said Cannot find module '../assets/image.jpg'.

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

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

export default Box;

The discussions I found online point to the need of defining a .d.ts file myself, so I created that index.d.ts file with this line.

declare module '*.jpg';

Then added "include": ["./src/index.d.ts"] inside tsconfig.json, after "compilerOptions" : {...}.

What did I miss? How can I fix the error TS is throwing?

John
  • 2,675
  • 3
  • 13
  • 20

19 Answers19

238

create index.d.ts file in folder src,and add this line

declare module '*.jpg';
Paolo
  • 21,270
  • 6
  • 38
  • 69
王玉略
  • 2,664
  • 1
  • 9
  • 8
  • 30
    Works but can you please enlighten me on **why and how** this works? Does this have to do something with typescript, or is it vscode? Is it like ignoring the error in all like linting issues? Please clarify. Thanks. – Rishav Dec 18 '20 at 10:36
  • @Rishav I think it's shorthand declaration specific https://www.typescriptlang.org/docs/handbook/modules.html `All imports from a shorthand module will have the any type.` – llamerr Feb 08 '21 at 17:01
  • 3
    what is so strange is, if I close the index.d.ts file in vs code. then the error returns. only when the file is open does it work. Does anyone know why? – loekTheDreamer Aug 06 '21 at 13:03
  • 1
    @loekTheDreamer I experience similar thing, error missing if I put reference directly in the file i.e put `/// ` – Abuw Mar 04 '22 at 13:49
150

If you literally wrote "include": ["./src/index.d.ts"] in tsconfig.json and you don't have a "files" setting, that means the project defined by tsconfig.json includes only the single file ./src/index.d.ts. When you open any other file in VS Code, VS Code uses a separate language service instance that doesn't use your tsconfig.json. Adjust your "include" setting to match all the .ts and .tsx files in your project, or just delete it and rely on the default behavior of including all files under the directory containing tsconfig.json.

Round 2

TypeScript is ignoring index.d.ts because it assumes that index.d.ts is generated from index.tsx and index.tsx is more likely to be up to date. Name your index.d.ts file something else, e.g., declaration.d.ts.

Matt McCutchen
  • 28,856
  • 2
  • 68
  • 75
  • 2
    I indeed literally wrote `"include": ["./src/index.d.ts"]` . Now I have removed that line and restarted VS Code, but the problem remains (`Cannot find module '../assets/image.jpg'`). Can the problem be caused by the bundler? But if VS Code uses a separate language service, I think it doesn't matter which bundler is being used. – John Oct 11 '18 at 13:14
  • 3
    Never mind, I think I found the problem. See the updated answer. – Matt McCutchen Oct 11 '18 at 13:20
  • 3
    Wow this is magic, thank you so much!! I spent almost the whole morning trying to figure out why it's not working :))) – John Oct 11 '18 at 13:43
  • 4
    Your Round 2 is the gift that keeps on giving. You just cleared up my issue with index.d.ts and SVGs, so thanks! – JesDaw Mar 12 '20 at 05:04
  • For your round 2, lunch is on me if we ever meet. Thank you so much! – Naser Mohd Baig Oct 02 '22 at 19:14
  • Round 2 also worked for good. Good stuff – travelerrrrrrr Dec 11 '22 at 13:11
110

Create module/type

# src/types/images.d.ts
declare module '*.jpg';
declare module '*.jpeg';

Change tsconfig.json

{
    "compilerOptions": {
        "typeRoots" : ["node_modules/@types", "src/types"]
    }
}
Claros
  • 107
  • 1
  • 9
mrfsb
  • 1,101
  • 1
  • 6
  • 2
  • Hi I would like to dig a little because i have created types/images.d.ts and this typeRoots option did not help, however this same declaration - "src/types" in include worked, now my include looks like so "include": ["src/*", "src/types"], its a bit like duplicating paths as src/* should cover the second use case as well, but it does not. Why include worked and typeRoots did not since "'typeRoots' specifies root folders in which the transpiler should look for type definitions" – seven Dec 20 '21 at 16:37
  • 3
    I did not need to modify typeRoots, simply dumping the d.ts file in the project worked. – Tamir Daniely Jan 17 '22 at 21:12
37

There can be many solutions to this problem

Solution #1:
Use require to include image

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

Solution #2:

Instead of importing images as import logo from "../../assets/logo.png"

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

then use it like

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

Solution #3:
There is a react-app-env.d.ts file in your src folder. If you don't see it, create a new file in the src folder named react-app-env.d.ts.

Now in your react-app-env.d.ts, add this code.

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

Solution #4:
Create declaration.d.ts in your src folder.
Then add following text in it.

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

Now you have to make your tsconfig.json look like this:

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

enter image description here


Solution #5:

Create a types folder in your src folder and add images.d.ts in this folder. Add below text in it.

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

Now configure tsconfig.json like this:

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

enter image description here


Mohammad Ayoub Khan
  • 2,422
  • 19
  • 24
  • `const logo = require("../../assets/logo.png")` gives the same error as `import logo from "../../assets/logo.png"`. Please test what you write before you post it. – Peter Schorn Feb 25 '23 at 02:03
  • **peter-schorn** It worked for me that's I posted it here, and you can clearly see that I got points for it, means it helped others, If it does not work for try another solution, Simple :) – Mohammad Ayoub Khan May 16 '23 at 17:38
  • I used Solution #4, and it works fine in my react-native project. Thanks – Dholu Aug 29 '23 at 15:37
23

there is a work around to it for example,

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

change this to

const logo =  require("../../assets/logo.png")
Shubham Kakkar
  • 581
  • 6
  • 4
23

This took me about an hour so I'm going to leave the solution that worked for me.

Matt McCutchen's solution half-worked for me, but I was still facing a VSCode error. To combat this, I moved my tsconfig.json and index.d.ts to the root directory, NOT the src. Now you want your tsconfig.json to look like this:

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

And for your index.d.ts, this:

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

(^ tweak to your typing needs)

Dharman
  • 30,962
  • 25
  • 85
  • 135
cr4z
  • 501
  • 6
  • 9
  • 3
    "To combat this, I moved index.d.ts to the root directory, NOT the src". This was my issue too. Thanks! – GG. Jan 10 '22 at 16:58
  • I tried the solution using "require('./image/location.jpg')" as well as this solution to create index.d.ts in the root with updated includes in tsconfig.json and both worked for me. – James F. Thomas Sep 09 '22 at 16:04
  • check if you have the extension image type capitalized so put this... declare module '*.png'; declare module '*.PNG'; – nativelectronic Sep 29 '22 at 23:02
  • For me, this SEEMS to work at first, but sooner or later the `module not found` error shows up again. I think this is a bug in parcel, we should not need a workaround or pages long discussions for something as rudimentary as loading an image! – Kokodoko Mar 11 '23 at 10:12
22

For "react": "^18.2.0" with Typescript do the following:

  1. Create a file called: declaration.d.ts in your src/ dir.
  2. Add this lines of code:

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

That's it the error should be gone.

Good luck!

Meet Bhalodiya
  • 630
  • 7
  • 25
ObiTech Invents
  • 408
  • 3
  • 6
  • Can you explain in detail what this does? – Manoj Apr 10 '23 at 14:02
  • Okay, what it does is It tells the typescript processor that any file with this extension is considered a module an can be important from anywhere in your project. Initially typescript processor will yell at you if it doesn't identify the file extensions when you import it into a typescript program. So with this declaration that red line will go away. – ObiTech Invents Apr 13 '23 at 08:50
  • Did not work for me, Maybe it is because of monorepo? or me using vite? – Kasir Barati May 04 '23 at 11:55
  • I guess that should be the reason – ObiTech Invents May 04 '23 at 12:20
  • @ObiTechInvents any idea on how to resolve it? – Kasir Barati May 06 '23 at 14:36
  • 1
    @KasirBarati What really worked for me was that at the root of src folder I created a file called `declaration.d.ts` and added the above lines of code then stop my local server and restart it again. If this didn't work for you can try creating a file called `types.d.ts` instead and repeat the same approach. God luck! – ObiTech Invents May 18 '23 at 15:49
8

There should be a file called "react-app-env.d.ts" that is created when you use create-react-app. This file classes all types of image files and many more as modules that can be imported. inside the file there should be the following:

/// <reference types="react-scripts" />
Peter McNulty
  • 99
  • 1
  • 4
5

I declared multiple image types, and had to put them in separate .d.ts files to make VS Code happy:

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
}

No tweaks to tsconfig, etc required.

Matt Rabe
  • 1,753
  • 19
  • 27
4

I've pasted:

/// <reference types="react-scripts" />

from an older project in my: react-app-env.d.ts and it worked.

In the latest versions of CRA (when TS is the chosen language), this file is automatically added to the src folder and contains the single line shown above. It is a directive to reference types from react-scripts.

SmartE
  • 523
  • 5
  • 11
Youssef Muhamad
  • 129
  • 1
  • 5
  • 2
    both lines are comments? – Akber Iqbal Apr 29 '20 at 04:35
  • 3
    They aren't just comments. As far as JavaScript is concerned, yes they are comments. However, the first line is a directive to eslint to ignore the linting rule for the next line. Eslint looks for these type of comments before linting the code. The second line is a way to reference types in your typescript files. See -> https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html – Dmase05 Sep 07 '20 at 02:40
  • Suppressing the error is not fixing the underlying issue and is a terrible practice! – Michael Eakins Jun 26 '21 at 14:22
  • @MichaelEakins The second line actually does clear the error rather than suppress it as you suggest. The first line is pretty much useless for the problem described in this question. – SmartE Sep 20 '21 at 00:14
  • in new react typescript installation this file was included, i accidentaly delete this file. thanks a lot – nalendro16 Mar 08 '23 at 12:14
3

Create a global.d.ts file inside your src directory or any rootDir

declare module "*.png" {
 export default "" as string
}

This will make use of an asset, in this case png image and also clear a vscode error

3

I test all of the replies and found the answer.

First, create a file with the name .d.ts in your route folder.

Then copy these lines into that.


declare module "*.png" {
  export default "" as string;
}
declare module "*.svg" {
  export default "" as string;
}
declare module "*.jpeg" {
  export default "" as string;
}
declare module "*.jpg" {
  export default "" as string;
}

Finally, go to tsconfig.json file in your route folder. and define new child.


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

your're go to go.

Vito Mohagheghian
  • 483
  • 1
  • 4
  • 7
1

This is worked for me

declare module "*.png" {
const src: string
export default src
}
1

I fixed adding file index.d.ts in root:

Paste the following code inside of it: /// <reference types="react-scripts" />

inside tsconfig.json, add: "include": ["src", "index.d.ts"]

Welcor
  • 2,431
  • 21
  • 32
PAINZOR
  • 11
  • 1
0

This error happens when you not included react-app-env.d.ts file in your src folder becoz you need two line of code for get rid of this error ==> <reference types="react-scripts" />

0

Example false positive

The image above illustrates how this error can arise falsely when you've miss quoted the path. Note I accidentally started with a double quote " and ended with a single quote '. Easy fix.

0

To address this issue, create a file named index.d.ts inside the src/Types directory. In this file, add the following declaration:

declare module '*.jpg';

This declaration allows TypeScript to recognize and import JPG image files without any type errors.

user16217248
  • 3,119
  • 19
  • 19
  • 37
0

For those who has this issue in a monorepo

First let's clarify one thing, I assume you're using create react app or vite and still have this issue. Although it really should not matter.

How I ended up in this mess?

I just had a monorepo and I was extending from the root tsconfig.json which was a place too keep every shared configuration in my entire monorepo. So I was extending from it in each and every sub repo I had in my monorepo. OK, Here is how my directory tree looks like

|-apps
|---backend
|-----src
|-----tsconfig.json
|---frontend
|-----src
|-----tsconfig.json
|-tsconfig.json

e.x. apps/frontend/tsconfig.json

{
    "extends": "../../tsconfig.json",
    "compilerOptions": {
        /* ... */
    }
}

Solution #1

So then TS was not able to find the file definition for the images. All I did was creating a new file in the root of my monorepo, named declarations.d.ts and pasting this code inside it:

// images
declare module '*.png' {
    const src: string;
    export default src;
}
declare module '*.jpg' {
    const src: string;
    export default src;
}
declare module '*.jpeg' {
    const src: string;
    export default src;
}
declare module '*.jfif' {
    const src: string;
    export default src;
}
declare module '*.pjpeg' {
    const src: string;
    export default src;
}
declare module '*.pjp' {
    const src: string;
    export default src;
}
declare module '*.gif' {
    const src: string;
    export default src;
}
declare module '*.svg' {
    const src: string;
    export default src;
}
declare module '*.ico' {
    const src: string;
    export default src;
}
declare module '*.webp' {
    const src: string;
    export default src;
}
declare module '*.avif' {
    const src: string;
    export default src;
}

Solution #2

Though you can resolve this issue by removing that extends in your ./apps/frontend/tsconfig.json. I chose to remove the extends since it was easier to rely on Vite rather my own code. Besides this way we have less code to worry of.

Kasir Barati
  • 606
  • 13
  • 24
0

if you have tried createing index.d.ts file in folder src, and adding declare module '*.jpg'; to it but it didn't work just rename index.d.ts to something else like export.d.ts .

monim
  • 3,641
  • 2
  • 10
  • 25