John
John

Reputation: 3215

Importing images in TypeScript React - "Cannot find module"

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?

Upvotes: 254

Views: 278705

Answers (24)

Shah Fahad
Shah Fahad

Reputation: 227

In simple term typescript is a statically typed language and it does comprehend these non code files. So, in order to treat non-code files as modules such as .png, .jpg etc.

  1. Create a /types directory inside /src
  2. Inside /types create a file name index.d.ts
  3. Within the file declare these
declare module "*.png";
declare module "*.jpg";

// ...rest of files extensions if any

Now, When you import a .png, etc files, it will be treated as a module.

Note: Incase of type checking, checkout the accepted answer in this thread

Upvotes: 1

BRONNER
BRONNER

Reputation: 21

For react-script app, add a "{my-app-name}-env.d.ts" file in src/

Content :

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

Upvotes: 0

Wilfred
Wilfred

Reputation: 1

Create a file custom.d.ts inside the src folder and add this lines:

declare module “.jpg” for jpg images declare module “.jpeg” for jpeg images declare module “.svg” for svg images declare module “.png” for png images

Upvotes: 0

王玉略
王玉略

Reputation: 3332

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

declare module '*.jpg';

Upvotes: 302

ahmnouira
ahmnouira

Reputation: 3481

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'
// ...

Upvotes: 3

Sergous
Sergous

Reputation: 1

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

Upvotes: 0

monim
monim

Reputation: 4383

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 .

Upvotes: 0

Mohammad Jawad Barati
Mohammad Jawad Barati

Reputation: 766

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.

Upvotes: 0

Yasser Amin Al Braidy
Yasser Amin Al Braidy

Reputation: 11

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.

Upvotes: 1

ObiTech Invents
ObiTech Invents

Reputation: 568

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!

Upvotes: 32

PAINZOR
PAINZOR

Reputation: 9

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

Upvotes: 0

Richard Tyler Miles
Richard Tyler Miles

Reputation: 683

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.

Upvotes: 1

Mohammad Mohagheghian
Mohammad Mohagheghian

Reputation: 483

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.

Upvotes: 3

Mohammad Ayoub Khan
Mohammad Ayoub Khan

Reputation: 2970

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


Upvotes: 55

Matt Rabe
Matt Rabe

Reputation: 2075

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.

Upvotes: 6

Imsamaritan
Imsamaritan

Reputation: 41

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

Upvotes: 4

Abdeldjalil Hachimi
Abdeldjalil Hachimi

Reputation: 121

This is worked for me

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

Upvotes: 1

cr4z
cr4z

Reputation: 581

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)

Upvotes: 24

MANAS RATHORE
MANAS RATHORE

Reputation: 11

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

Upvotes: 0

Peter McNulty
Peter McNulty

Reputation: 99

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

Upvotes: 8

Youssef Muhamad
Youssef Muhamad

Reputation: 139

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.

Upvotes: 4

mrfsb
mrfsb

Reputation: 1221

Create module/type

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

Change tsconfig.json

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

Upvotes: 122

Shubham Kakkar
Shubham Kakkar

Reputation: 591

there is a work around to it for example,

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

change this to

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

Upvotes: 24

Matt McCutchen
Matt McCutchen

Reputation: 30939

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.

Upvotes: 169

Related Questions