TypeStrong / ts-loader

TypeScript loader for webpack
https://johnnyreilly.com/ts-loader-goes-webpack-5
MIT License
3.45k stars 428 forks source link

TS2322: Type 'number' is not assignable to type 'SSRSlot' #1599

Open michaelcozzolino opened 1 year ago

michaelcozzolino commented 1 year ago

Expected Behaviour

The error in the pic should not be shown.

Actual Behaviour

when using dynamic slot with v-for with vue components, i'm getting the following errors:

error in /home/michael/Development/app/symfony-demo-vue-bug/assets/vue/components/Parent.vue.ts 8:00:25 AM

[tsl] ERROR in /home/michael/Development/app/symfony-demo-vue-bug/assets/vue/components/Parent.vue.ts(5,93) TS2322: Type 'number' is not assignable to type 'SSRSlot'.

error in /home/michael/Development/app/symfony-demo-vue-bug/assets/vue/components/Parent.vue.ts 8:00:25 AM

[tsl] ERROR in /home/michael/Development/app/symfony-demo-vue-bug/assets/vue/components/Parent.vue.ts(6,37) TS2769: No overload matches this call. The last overload gave the following error. Argument of type '<K extends string | number | symbol>(slotName: any) => { name: any; fn: Function; }' is not assignable to parameter of type '<K extends string | number | symbol>(value: any, key: K, index: number) => VNodeChild'. Type '{ name: any; fn: Function; }' is not assignable to type 'VNodeChild'. ` image

I tried to create a vue app with the same components without webpack and it compiles without errors.

Steps to Reproduce the Problem

steps to reproduce: 1) git clone https://github.com/michaelcozzolino/symfony-demo-vue-bug 2) composer install 3) yarn install 4) yarn watch or yarn build 5) observe the errors 6) php -S localhost:8000 -t public/

The components are in assets/vue/components and the purpose of them is to show a list of names by using dynamic slot names. by going to http://localhost:8000/en/blog/ the names are shown correctly.

Location of a Minimal Repository that Demonstrates the Issue.

https://github.com/michaelcozzolino/symfony-demo-vue-bug

antogno commented 1 year ago

I had the same problem and I tried to solve it by setting the transpileOnly option (see https://github.com/inertiajs/inertia/issues/1070#issuecomment-1084826500), but it didn't work.

The working solution for me was using the fork-ts-checker-webpack-plugin in webpack.mix.js, just like suggested here.

This is how my webpack.mix.js looks like now:

const mix = require('laravel-mix');

const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');

mix.webpackConfig({
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                loader: 'ts-loader',
                exclude: /node_modules/,
            },
        ],
    },
    plugins: [new ForkTsCheckerWebpackPlugin()],
    resolve: {
        extensions: ['.*', '.js', '.jsx', '.vue', '.ts', '.tsx'],
    },
})
    .setPublicPath('./webroot')
    .options({ processCssUrls: true });

mix.js('resources/js/foo.js', 'webroot/js/AssetMix')
    .ts('resources/js/bar/src/main.ts', 'webroot/js/AssetMix/bar.js')
    .vue({ version: 3 })
    .version();

if (!mix.inProduction()) {
    mix.sourceMaps();
}
l00sed commented 2 months ago

Thanks a lot for your response @antogno. The fork-ts-checker-webpack-plugin also worked for me. I was a little concerned at first because your configuration example is a little daunting. However, the Webpack plugin was key to getting it working.

The implementation was actually more straightforward than I expected, at least for Webpack >5.92.x:

const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
 /* or */
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';

/* then */
export default function() {
  return {
    ...
    plugins: [new ForkTsCheckerWebpackPlugin()],
    module: {
      rules: [
        {
          test: /\.ts$/,
          loader: 'ts-loader'
        }
      ]
    }
    ...
  }
}

The configuration example in their readme is good if you're not using ESM.