Importing images in TypeScript React - "Cannot find module"
Asked Answered
S

21

231

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?

Sidestep answered 11/10, 2018 at 11:42 Comment(3)
See github.com/Microsoft/TypeScript/issues/15146 – Materiel
you can do something like this https://mcmap.net/q/119833/-webpack-amp-typescript-image-import – Croak
Is there any @types package that provides these declarations out-of-the-box so that I don't have to provide them explicitly myself? – Tartan
B
159

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.

Bosley answered 11/10, 2018 at 12:58 Comment(6)
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. – Sidestep
Never mind, I think I found the problem. See the updated answer. – Bosley
Wow this is magic, thank you so much!! I spent almost the whole morning trying to figure out why it's not working :))) – Sidestep
Your Round 2 is the gift that keeps on giving. You just cleared up my issue with index.d.ts and SVGs, so thanks! – Pandich
For your round 2, lunch is on me if we ever meet. Thank you so much! – Voltammeter
Round 2 also worked for good. Good stuff – Torre
C
276

Create an index.d.ts file in the folder src, and add this line:

declare module '*.jpg';
Corrasion answered 24/7, 2019 at 6:27 Comment(5)
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. – Hardunn
@Hardunn I think it's shorthand declaration specific typescriptlang.org/docs/handbook/modules.html All imports from a shorthand module will have the any type. – Encomiast
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? – Hereditary
@Hereditary I experience similar thing, error missing if I put reference directly in the file i.e put /// <reference path="../../index.d.ts" /> – Arsenite
This didn't initially work for me. In my tsconfig file, include was set to "./src*" by default, which doesn't work. Changing it to "./src/**/*" and then adding the .d.ts file fixed it. – Grimsley
B
159

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.

Bosley answered 11/10, 2018 at 12:58 Comment(6)
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. – Sidestep
Never mind, I think I found the problem. See the updated answer. – Bosley
Wow this is magic, thank you so much!! I spent almost the whole morning trying to figure out why it's not working :))) – Sidestep
Your Round 2 is the gift that keeps on giving. You just cleared up my issue with index.d.ts and SVGs, so thanks! – Pandich
For your round 2, lunch is on me if we ever meet. Thank you so much! – Voltammeter
Round 2 also worked for good. Good stuff – Torre
B
115

Create module/type

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

Change tsconfig.json

{
    "compilerOptions": {
        "typeRoots" : ["node_modules/@types", "src/types"]
    }
}
Beige answered 14/9, 2020 at 13:45 Comment(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" – Antepast
I did not need to modify typeRoots, simply dumping the d.ts file in the project worked. – Brownedoff
D
49

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


Dupuy answered 17/7, 2022 at 3:40 Comment(3)
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. – Fibrinous
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 :) – Dupuy
I used Solution #4, and it works fine in my react-native project. Thanks – Romanticism
M
29

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!

Moy answered 29/10, 2022 at 13:9 Comment(6)
Can you explain in detail what this does? – Radiator
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. – Moy
Did not work for me, Maybe it is because of monorepo? or me using vite? – Varicella
I guess that should be the reason – Moy
@ObiTechInvents any idea on how to resolve it? – Varicella
@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! – Moy
N
24

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)

Naturopathy answered 9/1, 2022 at 3:54 Comment(4)
"To combat this, I moved index.d.ts to the root directory, NOT the src". This was my issue too. Thanks! – Each
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. – Sallyanne
check if you have the extension image type capitalized so put this... declare module '.png'; declare module '.PNG'; – Breezy
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! – Upton
S
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")
Suksukarno answered 19/6, 2019 at 21:4 Comment(3)
Will give you an error like require statement not part of an import statement – Shiftless
install requireJS (or was it commonJS) – Jonme
require works if you are using react < 17.0.1, 17.0.1 and above use import – Edrisedrock
M
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" />
Mcdermott answered 31/12, 2021 at 18:37 Comment(0)
A
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.

Articulate answered 28/3, 2022 at 16:21 Comment(1)
thx, this makes phpStorm also happy – Doze
C
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.

Centipede answered 29/4, 2020 at 2:19 Comment(5)
both lines are comments? – Donner
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 -> typescriptlang.org/docs/handbook/triple-slash-directives.html – Dextrocular
Suppressing the error is not fixing the underlying issue and is a terrible practice! – Brenna
@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. – Decorous
in new react typescript installation this file was included, i accidentaly delete this file. thanks a lot – Vincenza
P
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

Piece answered 28/3, 2022 at 8:9 Comment(0)
A
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.

Asci answered 31/8, 2022 at 16:44 Comment(0)
B
2

I had this issue in my Gatsby project with TypeScript, to fix this go to your declarations.d.ts file and add this.

declare module '*.jpg'
declare module '*.png'
declare module '*.svg'
// ...
Biotype answered 12/12, 2023 at 8:57 Comment(0)
B
1

This is worked for me

declare module "*.png" {
const src: string
export default src
}
Bydgoszcz answered 16/1, 2022 at 12:10 Comment(0)
L
1

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.

Longo answered 6/4, 2023 at 4:31 Comment(0)
C
1

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.

Corroborate answered 11/5, 2023 at 8:21 Comment(0)
Z
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" />

Zoba answered 1/1, 2022 at 7:54 Comment(0)
R
0

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"]

Rambert answered 31/1, 2023 at 11:16 Comment(1)
doesn't work for me – Plutocrat
V
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.

Varicella answered 18/5, 2023 at 16:24 Comment(0)
O
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 .

Ossuary answered 10/6, 2023 at 6:11 Comment(0)
C
0

In Blitz.js (based on Next.js) this works for me:

npx tsc-files --pretty --noEmit next-env.d.ts filenames

In package.json:

"lint-staged": {
  "*.{ts,tsx}": "tsc-files --pretty --noEmit next-env.d.ts"
}
Cole answered 30/9, 2023 at 21:5 Comment(0)

© 2022 - 2024 β€” McMap. All rights reserved.