5

I have the following piece of code within my .tsx file:

import L from 'leaflet';
import icon from 'leaflet/dist/images/marker-icon.png';
import iconShadow from 'leaflet/dist/images/marker-shadow.png';

And Typescript is complaining about the 2nd and 3rd line. Not only the linter, but the TS compiler itself.

Specifically the linter says that "It cannot find module 'blabla/icon.png' or its corresponding type declarations. However, importing L is ok.

Anyone has any idea why this is happening and how to solve this?

My tsconfig file looks like the following:

{
  "compilerOptions": {
      "outDir": "./dist/",        // path to output directory
      "sourceMap": true,          // allow sourcemap support
      "strictNullChecks": true,   // enable strict null checks as a best practice
      "module": "esnext",         // specify module code generation
      "jsx": "react",             // use typescript to transpile jsx to js
      "target": "es5",            // specify ECMAScript target version
      "allowJs": true,             // allow a partial TypeScript and JavaScript codebase
      "baseUrl": ".",
      "esModuleInterop": true,
      "allowSyntheticDefaultImports": true,
      "moduleResolution": "node",
      "resolveJsonModule": true,
      "isolatedModules": true,
      "paths": {
    }
  },
  "include" : ["src"],
  "exclude": ["node_modules", "dist", "config", ".vscode"]
}

Thank you in advance.

Javier Guzmán
  • 1,014
  • 2
  • 13
  • 27

2 Answers2

11

I solved this by creating an index.d.ts file with the following content:

declare module '*.png';
Javier Guzmán
  • 1,014
  • 2
  • 13
  • 27
2

Anyone has any idea why this is happening?

Because the import statement works only for JS modules and (this should be obvious) an image file is not a JS module.

Because importing modules and module bundlers have quite some history, there are hacks to make static assets look like JS modules (see e.g. https://github.com/rollup/awesome#other-file-imports). It is possible to configure a bundling toolchain in such a way that a CSS assets looks like a JS module, and said JS module is actually JS code that runs (and its effect is to append the wrapped CSS asset into a document body).

It's possible to apply such hacks to image assets, but since the semantics are not standardized, the behaviour will depend on how your toolchain is configured (e.g. compare @rollup/plugin-url, @rollup/plugin-image, rollup-plugin-file-as-blob, rollup-plugin-imagemin and rollup-plugin-smart-asset , all of which allow to import image assets but with wildly varying behaviour... and that's just for Rollup-based toolchains, I'm not even considering webpack, parcel or others here).

...and how to solve this?

Do not import image assets as if they were JS code, and be mindful of your toolchain.

IvanSanchez
  • 18,272
  • 3
  • 30
  • 45
  • Your answer seems to be very focused on JS, however this is Typescript. I am just saying because for example I have also a JS file that imports an image just like that and it works. On top of that, if I ignore the TS error it also works. – Javier Guzmán Jul 09 '20 at 05:33
  • I just found the answer, please, see my response down below. – Javier Guzmán Jul 09 '20 at 05:41