typescriptwebpacksveltewebpack-file-loaderwebpack-loader

Fix TypeScript warning about imports handled by Webpack loaders?


I'm setting up a new project using Svelte, Webpack, and TypeScript. It's based on this template, and running the scripts/setupTypeScript.js script after initial setup to switch to TypeScript.

When trying to import resources that are not TypeScript files, VSCode and TypeScript are showing errors about them:

import myContent from './some-file.txt';
// -> Cannot find module './some-file.txt' or its corresponding type declarations.ts(2307)

Technically this is working, but the errors are noisy and seem to be preventing live-reload. Is there some way to make TypeScript just ignore these imports and trust that Webpack will handle them? Some of these are binary files, so I can't just copy/paste them into .ts files either.

Webpack and TS configs are provided below:

webpack.config.js:

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const path = require('path');
const sveltePreprocess = require('svelte-preprocess');

const mode = process.env.NODE_ENV || 'development';
const prod = mode === 'production';

module.exports = {
    entry: {
        'build/bundle': ['./src/main.ts']
    },
    resolve: {
        alias: {
            svelte: path.dirname(require.resolve('svelte/package.json'))
        },
        extensions: ['.mjs', '.js', '.ts', '.svelte'],
        mainFields: ['svelte', 'browser', 'module', 'main']
    },
    output: {
        path: path.join(__dirname, '/public'),
        filename: '[name].js',
        chunkFilename: '[name].[id].js'
    },
    module: {
            rules: [
                {
                    test: /\.ts$/,
                    loader: 'ts-loader',
                    exclude: /node_modules/
                },
                {
                    test: /\.svelte$/,
                    use: {
                        loader: 'svelte-loader',
                        options: {
                            compilerOptions: {
                                dev: !prod
                            },
                            emitCss: prod,
                            hotReload: !prod,
                            preprocess: sveltePreprocess({ sourceMap: !prod })
                        }
                    }
                },
                {
                    test: /\.css$/,
                    use: [
                        MiniCssExtractPlugin.loader,
                        'css-loader'
                    ]
                },
                {
                    test: /\.(txt)$/,
                    use: ['raw-loader']
                },
                {
                    test: /\.(ttf|wasm)$/,
                    use: ['file-loader']
                },
                {
                    // required to prevent errors from Svelte on Webpack 5+
                    test: /node_modules\/svelte\/.*\.mjs$/,
                    resolve: {
                        fullySpecified: false
                    }
                }
        ]
    },
    mode,
    plugins: [
        new MiniCssExtractPlugin({
            filename: '[name].css'
        })
    ],
    devtool: prod ? false : 'source-map',
    devServer: {
        hot: true
    }
};

tsconfig.json:

{
        "extends": "@tsconfig/svelte/tsconfig.json",
        "include": ["src/**/*.ts", "src/node_modules/**/*.ts"],
        "exclude": ["node_modules/*", "__sapper__/*", "static/*"]
}

Solution

  • Add a global.d.ts file with the following contents and make sure it's picked up by your include:

    declare module "*.txt";
    

    This tells TS "any import ending with .txt is okay, treat it as any". Alternatively, export a default with another type:

    declare module "*.txt" {
        const content: string;
        export default content;
    }