100

I found a solution here: Webpack & Typescript image import

But I am getting error for this:

[ts]
Types of property 'src' are incompatible.
  Type 'typeof import("*.png")' is not assignable to type 'string | undefined'.
    Type 'typeof import("*.png")' is not assignable to type 'string'.

I guess I need to cast import somehow, but can't figure out how. I am doing this in React. I saw that src attribute is defined as string | undefined, that is why error is popping.

Here is code:

import * as Logo from 'assets/images/logo.png';

HTML:

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

And definition based on above mentioned solution:

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

Tsconfig:

{
  "compilerOptions": {
    "baseUrl": "./",
    "jsx": "react",
    "lib": ["es5", "es6", "dom"],
    "module": "commonjs",
    "noImplicitAny": false,
    "outDir": "./dist/",
    "sourceMap": true,
    "strictNullChecks": true,
    "target": "es5",
    "typeRoots": [
      "custom_typings"
    ]
  },
  "include": ["./src/**/*.tsx"],
  "exclude": ["dist", "build", "node_modules"]
}
5
  • 1
    According to here you should use require instead of import. So it should look like this: const Logo = require('assets/images/logo.png') Commented Jul 3, 2018 at 21:21
  • Yep i saw that. But that is not elegant way of doing this. The thing is that when you do import it works when you load app. But you get lint error. Commented Jul 3, 2018 at 21:23
  • 2
    import works so it should be used. @MarioPetrovic a default import has no name. That is why you can leave out the * as part. import Logo from './logo.jpg' is fine because it's equivalent to const Logo = require(./logo.jpg) Commented Dec 24, 2020 at 10:00
  • <img src={require('assets/images/logo.png')} /> works. What makes it not elegant, if you only need to reference it in that one line? To me, it feels more elegant and bulletproof than modifying d.ts files. Commented Feb 28, 2022 at 9:21
  • Well it is probably more of a judgement call. But if you setup it with d.ts and use it later in your project it makes it more organic and consistent with regular importing. Commented Feb 28, 2022 at 11:05

6 Answers 6

191
+50

One of the ways to get rid of that error is by modifying d.ts file as follows:

declare module "*.png"

remove

{
  const value: string;
  export default value;
}

or alternatively you can do:

declare module "*.png" {
  const value: any;
  export default value;
}

Update

The best solution with type-checking is:

declare module "*.png" {
   const value: any;
   export = value;
}
Sign up to request clarification or add additional context in comments.

15 Comments

You can also try this: declare module '*.png' { const value: string; export = value; }
I get: TS1192: Module '"*.png"' has no default export.
@danielrvt you were probably not doing it on d.ts / custom.d.ts, but somewhere else...
I had trouble getting this to work due to this long-standing issue. As soon as I moved my wildcard declare module statements into their own typings file, rather than an existing globals.d.ts I had for other stuff (which happened to import an interface declaration...), I was able to import LOGO from "./logo.png".
The .d.ts file needs to be put into the src/ folder to be working, in case anybody else encounters that problem putting it in the project root.
|
45

For react-native

create global.d.ts file on project root folder and just add next lines there

declare module '*.png' {
  const value: import('react-native').ImageSourcePropType;
  export default value;
}

4 Comments

That's a nice solution, you can also change the value type as your need.
This works well, but I wish TypeScript checked that files exist when importing them. As-is, it allows me to import a non-existent file, which would result in a runtime error. I've been searching for a way to preserve file existence checks like we get from importing JS/TS but haven't found a way yet.
for react-native I've just created a types.d.ts in the root with the simplest answer and worked like a charm: `declare module "*.png"
@FacundoColombier sure. It is just the same, but with type. And what type did you get in code? It will solve problem with file absence? :)
5

I created the index.d.ts and added 'declare module "*.jpg"' it didn't work but when I changed the name to custom.d.ts (or any other name) it worked fine.

Comments

2

In my case, even with the global.d.ts configured, it wasn't working due to the import. instead of

import * as Logo from 'assets/images/logo.png';

i used:

import image from 'assets/images/logo.png';

it worked fine.

Comments

1

You first need to create a new TypeScript declaration file with the file extension .d.ts. For my project I named it custom.d.ts and put it in my src directory. Then add the code suggested in the accepted answer to that file:

declare module "*.png" {
   const value: any;
   export = value;
}

Comments

0

If you're using Vite, Vite already provides the type definitions for image import in vite/client.d.ts.

Create vite.d.ts in your root directory with this content:

    /// <reference types="vite/client" />

Include vite.d.ts in your tsconfig.json:

{
  "compilerOptions": {
// ...
  },
  "include": ["src", "vite-env.d.ts"], // <--- this
  "exclude": ["node_modules", "dist"]
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.