ts-loader icon indicating copy to clipboard operation
ts-loader copied to clipboard

Unable to load default and exported from vue templates

Open jrbasso opened this issue 2 years ago • 9 comments

Expected Behaviour

I expect to import default and exported interfaces from ts file/portion. It was working on ts-loader 8.x with webpack 4.x and it's failing on ts-loader 9.x with webpack 5.x.

It even works on ts-loader 8.x using webpack 5.x (not recommended since I believe it's not designed for).

Actual Behaviour

Typescript return the error TS2614 when trying to do an import like import HelloWorld, { HelloProp } from './components/HelloWorld.vue';

See the full output:

(ts-loader-9)$ ./node_modules/.bin/webpack
assets by status 53.1 KiB [cached] 1 asset
orphan modules 416 KiB [orphan] 15 modules
runtime modules 500 bytes 2 modules
./src/main.ts + 14 modules 415 KiB [built] [code generated]

ERROR in /Users/juanbasso/tmp/webpack5/hello-world-no-class/src/App.vue.ts
3:21-30
[tsl] ERROR in /Users/juanbasso/tmp/webpack5/hello-world-no-class/src/App.vue.ts(3,22)
      TS2614: Module '"*.vue"' has no exported member 'HelloProp'. Did you mean to use 'import HelloProp from "*.vue"' instead?
ts-loader-default_0c5a263502dc9404

webpack 5.48.0 compiled with 1 error in 5039 ms

Steps to Reproduce the Problem

I created a sample to reproduce the working and not working versions:

  • ✅ ts-loader 8.x with webpack 4.x: https://github.com/jrbasso/ts-loader-import-bug/tree/ts-loader-8
  • ✅ ts-loader 8.x with webpack 5.x: https://github.com/jrbasso/ts-loader-import-bug/tree/ts-loader-8-webpack5
  • ✖️ ts-loader 9.x with webpack 5.x: https://github.com/jrbasso/ts-loader-import-bug/tree/ts-loader-9

To reproduce, simply checkout the branch and run npm ci && ./node_modules/.bin/webpack

Location of a Minimal Repository that Demonstrates the Issue.

See steps to reproduce.

jrbasso avatar Aug 03 '21 02:08 jrbasso

@jrbasso, I don't use Vue but I took a look at your ts-loader-9 repo. I saw the same error message you report.

TypeScript is complaining that Module '"*.vue"' has no exported member 'HelloProp', which is true, the definition of *.vue in shims-due.d.ts does not include HelloProp. If you include HelloProp as an export in the *.vue module as below the error disappears:

declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
  export interface HelloProp {
    title: string,
    caption: string
  }
}

I appreciate this may not be a generic solution to this issue. The thread below discusses this error when importing interfaces from Vue components:

https://stackoverflow.com/questions/65738176/how-to-avoid-ts2614-error-when-importing-interfaces-from-vue-components

I don't know why it worked in ts-loader-8 but it seems to me that the error TypeScript is reporting is correct. Perhaps the Vue community has found a solution.

appzuka avatar Aug 03 '21 20:08 appzuka

Fair enough. That was my understanding, but since it was working on ts-loader 8.x I thought it had some magic internally. To avoid adding the interface on the shim I created a definition file just for the class that exports the interface.

Do you want to leave this ticket open to handle a fix on 8.x or should it be closed?

jrbasso avatar Aug 05 '21 00:08 jrbasso

I'd quite like for this to be fixed in ts-loader - I think it's an issue. But as I'm not a Vue user I'm not well placed to help.

My guess is that the answer lies in looking at the src files on this PR:

https://github.com/TypeStrong/ts-loader/pull/1251

That's where we went from ts-loader 8 to 9 and where I assume the break happened. (Maybe worth checking that v9.0.0 was the first version where this didn't work)

The src changes are actually pretty minimal, so I expect diagnosis might be fairly straightforward

johnnyreilly avatar Aug 05 '21 05:08 johnnyreilly

I've just run into this while trying to import interfaces exported from Vue SFCs. I'm not using the shim for vue so the resulting error is a TS2307:

ERROR in /path/to/importing/component.vue.ts(LINE,CHAR)
TS2307: Cannot find module './path/to/exporting/component.vue' or its corresponding type declarations.

Downgrading from 9.2.6 to 8.3.0 also fixes the problem for me (maintaining running webpack 5). I can verify that 9.0.0 was the version that broke things. I'm going to take a look at the PR above and try and isolate what's causing it.

olsgreen avatar Feb 19 '22 14:02 olsgreen

@johnnyreilly I don't suppose you still have a copy of the feat/webpack-5 branch? There's nothing that stands out for me as a breaker, I was going to go commit by commit through your changes but can't sync the un-merged commits as the branch no longer exists.

olsgreen avatar Feb 19 '22 15:02 olsgreen

I have a feeling I haven't I'm afraid. Did a rm -rf along the way. But I'd take a look at the diffs in the src folder alone. If memory serves, there aren't many. It was mostly a case of deleting code and using the built in webpack types (which shouldn't be relevant)

johnnyreilly avatar Feb 19 '22 16:02 johnnyreilly

Actually comparing the transpiled code for ts-loader 8 as opposed to 9 might be more revealing in terms of different running JavaScript (which is what is relevant for your case I believe)

johnnyreilly avatar Feb 19 '22 16:02 johnnyreilly

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Apr 28 '22 01:04 stale[bot]

Here's a workaround for the ts-loader 9.x.

diff --git a/webpack.config.js b/webpack.config.js
index 34a6296..a140bbe 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -20,8 +20,12 @@ module.exports = {
             },
             {
                 test: /\.vue$/,
-                loader: 'vue-loader',
-            }
+                use: [{
+                    loader: "vue-loader"
+                }, {
+                    loader: "ts-loader"
+                }]
+	    }
         ],
     },
     output: {

jolting avatar Sep 10 '22 03:09 jolting