TS2345 Argument of type is not assignable to parameter of type: using one module that's declared in another module

4.5k views Asked by At

I've been trying to figure out an issue using Webpack, webpack-merge, and separate development Webpack files using TypeScript, and I've sort of realized that I need to declare a type alias function that is passed from a webpack.common.ts file to a webpack.dev.ts file.

Here's what I was trying to do originally. I have a webpack.common.ts file that loads in a basic configuration:

import { Configuration } from 'webpack';
import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin';

const common: Configuration = {
  module: {
    rules: [
      {
        exclude: /node_modules/,
        test: /\.ts(x?)$/,
        use: [{ loader: 'ts-loader' }],
      },
      {
        enforce: 'pre',
        loader: 'source-map-loader',
        test: /\.js$/,
      },
    ],
  },
  resolve: {
    extensions: ['.ts', '.tsx', '.js'],
    plugins: [new TsconfigPathsPlugin({})],
  },
};

export default common;

I then have separate prod and dev Webpack files that use webpack-merge. Here is webpack.dev.ts:

import { Configuration } from 'webpack';
import common from './webpack.common';
import path from 'path';

const __dirname = path.resolve();

const dev: Configuration = merge(common, {
  devServer: {
    compress: true,
    contentBase: path.join(__dirname, 'dist/dev'),
    historyApiFallback: true,
    hot: true,
    open: true,
    port: 9000,
  },
  devtool: 'source-map',
  externals: {
    'react': 'React',
    'react-dom': 'ReactDOM',
  },
  mode: 'development',
});

export default dev;

This results in an error inside the merge method:

Argument of type 'import(".../node_modules/@types/webpack/index").Configuration' is not assignable to parameter of type 'import(".../node_modules/@types/webpack-merge/node_modules/@types/webpack/index").Configuration'.

Based on that, it looks webpack-merge has its own Webpack typings, and Webpack and webpack-merge are using two different Configuration types.

I tried updating the webpack-merge typings so that it would import Webpack's typings rather than its own set.

Inside webpack-merge's index.d.ts file:

// import { Configuration } from 'webpack'; 
import { Configuration } from '../webpack';

Doing that, I now get a different error from inside the merge method in webpack.dev.ts:

Argument of type '{ devServer: { compress: boolean; contentBase: string; historyApiFallback: boolean; hot: boolean; open: boolean; port: number; }; devtool: "source-map"; externals: { 'react': string; 'react-dom': string; }; mode: "development"; }' is not assignable to parameter of type 'Configuration'.

Hovering over merge in VS Code, this is type information I get for it:

(alias) merge(...configs: Configuration[]): Configuration

Should I be updating the import path for webpack-merge so that it uses the same type declarations? And how can I update the merge typing to accept these webpack-dev-server types (without having to use any)?

1

There are 1 answers

0
user650881 On BEST ANSWER

Extending the TypeScript typing for the webpack Configuration to define devServer as recommended in this DefinitelyTypes issue response by uipoet (and transcribed here) worked for me.

import { Configuration as WebpackConfiguration } from "webpack";
import { Configuration as WebpackDevServerConfiguration } from "webpack-dev-server";

interface Configuration extends WebpackConfiguration {
  devServer?: WebpackDevServerConfiguration;
}

export const configuration: Configuration = {
  ...
  devServer: {
    historyApiFallback: true,
    hot: true,
    port: 3000
    ...
  }
  ...
}

Tested with @types/webpack 5.28.0 and @types/webpack-dev-server 3.11.4.

References: