Dzulqarnain Nasir

Webpack-ing static content for TypeScript

January 14, 2019 | 2 Minute Read

Here’s a quick one.

I’ve recently started cleaning up the code for one of my projects, and one of the things I did was introducing the file-loader plugin, and converting static content references throughout my codebase.

It was a pretty straightforward process for image URLs within my Vue files, but then I also have code that switches out the background image of elements based on specific conditions. This requires the static content URL to be imported into the code that handles the logic.

For example:

// component class

get centerOverlayStyle() {
    let backgroundImage = null;

    if (this.inputMode === MapInputMode.PICKUP) backgroundImage = 'url(/public/static/pickup-icon.svg)';
    if (this.inputMode === MapInputMode.DROPOFF) backgroundImage = 'url(/public/static/dropoff-icon.svg)';

    return { backgroundImage };
}

In order for me to use the image files emitted by file-loader, I need to replace the image paths with the ones generated by the plugin.

According to the documentation, I can simply import the image file into my code, and assign it to a local variable, and use it whenever I need reference to the image URL anywhere in my code. file-loader would resolve the path, allowing my code to point to the correct URL.

import pickupIcon from '@/static/pickup-icon.svg';
import dropoffIcon from '@/static/dropoff-icon.svg';
// component class

get centerOverlayStyle() {
    let backgroundImage = null;

    if (this.inputMode === MapInputMode.PICKUP) backgroundImage = `url(${pickupIcon})`;
    if (this.inputMode === MapInputMode.DROPOFF) backgroundImage = `url(${dropoffIcon})`;

    return { backgroundImage };
}

Unfortunately, while this works for regular JavaScript, TypeScript sees this as a problem.

Cannot find module '@/static/pickup-icon.svg'.
Cannot find module '@/static/dropoff-icon.svg'.

TypeScript assumes that everything we import are modules, and if it cannot determine this to be the case, it will log an error. The definition of a module can either be determined by the imported TypeScript (.ts/.tsx) file, or by a type declaration file (.d.ts) that the code depends on. [Reference]

So, the solution is quite simple. We just have to tell TypeScript about our image files by adding a type declaration file (d.ts.), and declare the image files we’re using in our project as a module.

// images.d.ts

declare module '*.svg';
// duplicate for other image file extensions

Et voilà. Problem solved.