82

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 cant 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"]
}
Matt McCutchen
  • 28,856
  • 2
  • 68
  • 75
Mario Petrovic
  • 7,500
  • 14
  • 42
  • 62
  • 1
    According to [here](https://stackoverflow.com/questions/36148639/webpack-not-able-to-import-images-using-express-and-angular2-in-typescript/36151803#36151803) you should use require instead of import. So it should look like this: `const Logo = require('assets/images/logo.png')` – mjoppich Jul 03 '18 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. – Mario Petrovic Jul 03 '18 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)` – ThaJay Dec 24 '20 at 10:00
  • `` 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. – jrc Feb 28 '22 at 09: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. – Mario Petrovic Feb 28 '22 at 11:05

4 Answers4

168

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;
}
Piyush Zalani
  • 3,686
  • 1
  • 13
  • 29
  • Already tried to modify from `string` to `any` and it wont help. It seems that const value is not getting considered when resolving type of imported. As for removing block, it wont work either. – Mario Petrovic Jul 03 '18 at 22:07
  • 1
    You can also try this: declare module '*.png' { const value: string; export = value; } – Piyush Zalani Jul 03 '18 at 22:10
  • Hey. Just tried it with `export = value` and it worked. It also gives `string` as type for imported `Logo`. Also, sorry, but your solution to exclude block of code actually worked, so only `declare module "*.png"` worked but didn't give type. So please modify your answer to include solution with `export = value` as best option because of type checking. Thanks very much. – Mario Petrovic Jul 04 '18 at 07:55
  • I want to import svg, png, jpg, jpeg, ... so I have to copy paste declare module or could we define something like regular expression –  coinhndp Oct 29 '18 at 07:04
  • 14
    I get: TS1192: Module '"*.png"' has no default export. – danielrvt Mar 18 '19 at 14:28
  • 1
    @danielrvt you were probably not doing it on `d.ts` / `custom.d.ts`, but somewhere else... – Andrea Ligios Feb 14 '20 at 14:34
  • I added the last solution to my `custom.d.ts`, and it fixed my tslint error, thank you! – Liran H Aug 02 '20 at 14:03
  • downvoted this answer. This does not work `Parsing error: Only declares and type imports are allowed inside declare module`. I tried declare module `"*.png" { const value: any; export = value; }` and also tried `declare module '*.png' { const value: string; export = value; }` and it's complaining about const – PositiveGuy Aug 03 '20 at 23:24
  • 7
    I had trouble getting this to work due to [this long-standing issue](https://github.com/microsoft/TypeScript/issues/28097). 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"`. – Coderer Dec 23 '20 at 16:55
  • 9
    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. – Axel Köhler Oct 19 '21 at 11:40
  • I'm annoyed to say my issue is just with IntelliJ IDE just underlining the import. It compiles just fine and even using `// @ts-ignore` suppresses the red underline error. I've tried everything to gain the smart resolution for my IDE; changing syntax was really a last resort `const logo = require("*.png");` which was successful in both compilation and now on my editor. – Richard Tyler Miles Nov 10 '21 at 18:06
  • I get the following error when declaring image imports as a string: `'string' only refers to a type, but is being used as a value here.ts(2693)` – Kokodoko Jan 31 '22 at 19:06
  • For me the only solution is to ignore the error with `// @ts-ignore`. I can't fathom why such a basic function as loading an image is not working in parcel ? – Kokodoko Jan 31 '22 at 19:18
  • @PiyushZalani in your answer, can you describe why the "best solution" in the Update section is better than the original solution? – clemp6r Feb 07 '22 at 12:12
36

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;
}
Vitalii Obideiko
  • 1,726
  • 1
  • 13
  • 16
  • That's a nice solution, you can also change the value type as your need. – nima Apr 06 '22 at 06:59
  • 1
    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. – stephen.hanson Jun 13 '22 at 14:17
  • 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" – Facundo Colombier Jul 24 '23 at 20:03
  • @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? :) – Vitalii Obideiko Jul 24 '23 at 21:28
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.

YASSINE
  • 100
  • 1
  • 5
1

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.

Ana PL
  • 11
  • 2