Closed borislitvak closed 7 years ago
This is because you don't have declarations of .vue
files, then the typescript compiler cannot load them. You need to declare general declaration of .vue
file in your project or generating each .vue
file declaration by using vuetype
I cannot thank you enought for your answer, @ktsn ! You've made my day!
Without knowing the above, how would you approach debugging this problem? Do you 'node debug webpack'? If not, how do you know where the problem is? After all, you don't see the generated .d.ts file nor there are any webpack/vue-loader logs.
Thank you, Boris
Just see the compiler error log. Cannot find module
means the TS compiler cannot find the typescript file or its declaration.
FYI: https://www.typescriptlang.org/docs/handbook/modules.html
Happy someone else had the same question. Thank you!
THANK YOU !!
Oh! Why this isn't added into official doc?
I can't seem to get this thing working without vuetype.
Is using vuetype mandatory?
I had almost the same problem, but the above only solved it within Visual Studio Code. When running the development server I got the following error:
Module build failed: Error: Could not find file: '/src/sections/search-result/search-result.vue'.
I solved it by changing the webpack ts-loader config from:
{
test: /\.tsx?$/,
loader: "ts-loader"
}
to
{
test: /\.tsx?$/,
loader: "ts-loader",
options: {
appendTsSuffixTo: [/\.vue$/]
}
}
like they do in the upcoming typescript template for vue-cli.
@ktsn Including the sfc.d.ts
file allows me to import .vue
modules in my typescript files, but it seems to conflict with the Vetur plugin. In my .vue
components, the path / file checking for imports is completely disabled when I use the .d.ts file! Also, changes in .vue files are not reflected in autocomplete anymore.
index.ts
import App from './components/app.vue' // only works with the sfc.d.ts file
app.vue
<script lang="ts">
import Vue from 'vue'
import Card from "./notexist/card.vue" // only works WITHOUT the sfc.d.ts file!
</script>
Including vue-shims.d.ts
in the files
property of tsconfig.json
fixed the issue for me:
"files": [
"./static/types/vue-shims.d.ts"
]
u can import component without use suffix .vue
Home.vue
<template>
<div class="home">
home ...
</div>
</template>
<script lang="ts" src="./Home.ts">
</script>
Home.ts
import { Vue } from 'vue-property-decorator';
@Component
export default class Home extends Vue {}
App.vue
// doesn't work
// import Home from './views/Home.vue';
// well done import Home from './views/Home'
@ktsn I previously used the general vue declaration ("vue-shim") you linked to, but I'm facing a problem now that I'm trying to augment the Vue type with a custom property on the prototype:
In order for VS Code to recognize the plugin, I have to declare a module for 'vue/types/vue':
import Vue from 'vue'
import { MomentTimezone } from 'moment-timezone'
declare module 'vue/types/vue' {
export interface Vue {
$moment: MomentTimezone
}
}
This conflicts with the vue-shim, which declares a module for '*.vue', so now I have TS support for my $moment
method on the Vue prototype, but tslint cannot deal with my path aliases for importing vue SFCs and gives me lots of TS2307 warnings in the terminal at compile time (even though the app compiles fine). How can I keep support for path aliases but also augment the Vue type for extending the Vue prototype?
@TychoCRD I'm also running into this issue, I was wondering if you ended up solving it?
My last resort here is to use @ts-ignore
to get rid of the compile time errors.
@ktsn Thank you. But it is not resolve. Then i try resolve as TypeScript-Vue-Starter,
// src/vue-shims.d.ts
declare module "*.vue" {
import Vue from "vue";
export default Vue;
}
it resolve.
@borislitvak @ktsn @korziee In my case , when I try to import some vue
files into the jest
files written in ts
format, vs code hint that I got an error in forms [ts] cannot find module... 2307
. I think that it must be a problem for vs code to resolve the module path, so I include all the paths that typescript should treat that files, in tsconfig.json
, just like this:
{
"include": [
"src/**/*.ts",
"src/**/*.vue",
"test/**/*.ts"
],
"exclude": [
"node_modules"
],
"files": [
"ts-custom.d.ts"
],
"types": [
"jest"
],
"compilerOptions": {
"outDir": "./dist/",
"target": "es5",
"module": "esnext",
"moduleResolution": "node",
"esModuleInterop": true,
"strict": true,
"noImplicitReturns": true,
"allowJs": false,
"sourceMap": true,
"pretty": true,
"removeComments": true
}
}
and finally, vs code feel so happy. :laugh:
Hey @ktsn your link "https://github.com/vuejs/vue-class-component/blob/master/example/sfc.d.ts" is broken. I can't find its equivalent through google.
I have this shim that I use in my projects:
declare module "*.vue" {
import Vue from "vue";
export default Vue;
}
But this obviously doesn't work for named exports. vuetype doesn't appear to work for them either. I'd like to find out if there's a way to use Vue and TypeScript with named exports because they cut down on potential typos.
@beetaa Many thanks for saving my time. For those unfamiliar like me, important elements are:
Create a ts-shim.d.ts
declare module "*.vue" {
import Vue from "vue";
export default Vue;
}
I copied from @beetaa template's
Update tsconfig.json
. I am using Nuxt so I include everthing
{
"include": ["**/*.ts", "**/*.vue"],
"exclude": ["node_modules"],
"files": ["ts-shim.d.ts"]
}
Inspired by the same repo
For reference, as my case was also in testing file, my jest.config.js
is:
module.exports = {
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/$1',
'^~/(.*)$': '<rootDir>/$1'
},
transform: {
'^.+\\.ts?$': 'ts-jest',
'.*\\.(vue)$': 'vue-jest'
},
moduleFileExtensions: ['ts', 'js', 'vue', 'json']
};
It is implemented here
The link provided in the upvoted comment is broken.
What is the solution to this problem as of Jun, 2019?
As of today, vuetype has not been updated since February 2018 and won't work with non-class-based Vue component declaration.
Seems like we still don't have a way to directly import .vue
files as TypeScript classes and infer their type signature
Then the obvious question is: Why is this still closed then?
Is there a new, open issue?
Or does "it technically works but your IDE won't notice" count as a valid argument?
@skovmand Your solution worked for me as well, but i haven't notice it untill I disabled the "Vetur" extension in Visual Studio Code. It keeps the red error underline when importing Vue components without .vue
suffix despite everithing worked fine.
The shims-vue.d.ts
solution, as described by @Al-un is already implemented in the Vue CLI Typescript template, but I'm still getting this error.
Ugh forget that. I just forgot to include the .vue
extension:
import Foo from 'foo.vue'; // Works
import Foo from 'foo'; // Does not work!
I also have to include the .vue extension when importing components or I get the same errror.
I am using
"@vue/cli-plugin-babel": "^4.1.2", "@vue/cli-plugin-pwa": "^4.1.2", "@vue/cli-plugin-typescript": "^4.1.2", "@vue/cli-service": "^4.1.2",
It seems there is something missing still. I have tried using shims-vue.d.ts in the files section with no results.. Any help would be appreciated. :)
@NavidMitchell I have same issue.
Does not work:
// index.ts
import Sample from 'components/Sample'
// App.vue
<script lang="ts">
import Sample from 'components/Sample'
</script>
Does work:
// index.ts
const Sample = require('components/Sample')
// index.ts
import Sample from 'components/Sample.vue'
// index.js
import Sample from 'components/Sample'
// App.vue
<script lang="ts">
import Sample from 'components/Sample.vue'
</script>
// App.vue
<script lang="js">
import Sample from 'components/Sample'
</script>
It seems the issue is in ts-loader..
@vue/cli:4.2.3
shims-vue.d.ts
is presentwebpack is well configured according to previous comments
{
"test": "/\\.ts$/",
"use": [
// ....
"options": {
"appendTsSuffixTo": [
"/\\.vue$/"
]
}
]
}
I followed the upvoted comment but it didn't work. i checked ts-loader version was 4.5.1. After I downgraded it to 4.1.0 it worked.
Looks like there was a breaking change, but the semver ^4.1.0 will not work. For time being change it to exact match 4.1.0
If declare module "*.vue"
not working it is because the declaration file contain some code that not acceptable by the ts.
I gave up on generating proper .d.ts
files for .vue
files (instead of using the shim) and just put everything that I needed to import from the .vue
file into an actual .ts
file. I.e. instead of this, which does not work:
// foo.vue
export enum Stuff {
...
}
@Component
export default class Foo extends Vue {
public baz() {
}
}
// bar.vue
import { Stuff } from "./foo.vue"
// Does not work by default because it is using the shim which does not know about `Stuff`
I do this:
// stuff.ts
export enum Stuff {
...
}
// foo.vue
import { Stuff } from "./stuff"
@Component
export default class Foo extends Vue {
public baz() {
}
}
// bar.vue
import { Stuff } from "./stuff"
Definitely easier than faffing around with .d.ts
files. The only downside is that the shim makes every .vue
file act as if it is exporting a Vue
object. So if you do this:
import Foo from "./foo.vue"
It does compile but Typescript thinks that Foo
is just an alias for Vue
, so if you try to call Foo.baz()
you'll get an error.
My ultimate solution is to switch to React which is simply much much better at integrating with Typescript (it also type checks templates which is a pretty huge flaw in Vue).
@Timmmm
https://github.com/quasarframework/quasar-testing/issues/48#issuecomment-507763139
Here, at Demo component
section, I explain how to use a Double File Component fashion to make inference work
import Foo from 'foo.vue'; // Works import Foo from 'foo'; // Does not work!
This answer is downvoted, but for some reason only this works. Though I do not undrstand why...
My ultimate solution is to switch to React which is simply much much better at integrating with Typescript (it also type checks templates which is a pretty huge flaw in Vue).
Hi @Timmmm, the .vue
files are only a suggestion from Vue, as the lib itself is not entirely opinionated on how you render the templates and how you inject or inline the CSS. You can also use Vue with separate templates, even in JSX, just like React. It can be considered non-standard but it works (in fact, I prefer it like that, .vue
files tend to get very messy). Switching to React is, though, an understandable way to go if you're really into TS.
u can import component without use suffix
.vue
- Home.vue
<template> <div class="home"> home ... </div> </template> <script lang="ts" src="./Home.ts"> </script>
- Home.ts
import { Vue } from 'vue-property-decorator'; @Component export default class Home extends Vue {}
- App.vue
// doesn't work // import Home from './views/Home.vue'; // well done import Home from './views/Home'
If I want to also separate template, is there any workaround?
Well, you can move the style part into a standalone file and reference it as you do for the script part. In that way you only get the template part in the .vue file
For Vue3 (found in @fredkschott 's snowpack + vue + typescript template)
Declare the type of your *.vue
files in /types/shims-vue.d.ts
(or wherever you'd prefer)
declare module '*.vue' {
import { defineComponent } from 'vue';
const component: ReturnType<typeof defineComponent>;
export default component;
}
then tell typescript to include it in /tsconfig.json
{
"include": [
"types",
// ...
],
// ...
}
@ninofiliu I did that but I still cannot import Vue components via
import MyComponent from "@/components/MyComponent";
only via
import MyComponent from "@/components/MyComponent.vue";
Is there any other change required?
@Anubarak well yes, if you write declare module '*.vue'
that'll only declare types when you import files that match *.vue
, so "@/components/MyComponent.vue"
is ok, but not "@/components/MyComponent"
@ninofiliu Thank you very much for your answer. That explains it. Guess I'll just always import them as .vue
files then.
What's the reason for the vue shim not to be included in vue's own typescript support? Do I really have to have this 'noise' file in my project that could easily be in the library I'm working with? My webpack build doesn't compile without this thing:
shims-vue.d.ts
declare module '*.vue' {
import Vue from 'vue';
export default Vue;
}
@ninofiliu I have found that the ...ReturnType<typeof defineComponent>
solution can royally mess things up.
To be more specific, when you are using Vue 3 + options api + using a components:{SomeComp}
and return a value from any lifecycle method or watch handler that previously has accessed any this
value. Debugging this was immensely stupid and time consuming, but I have found the following solution to not bring any of these issues:
declare module '*.vue' {
import { DefineComponent } from 'vue';
const component: DefineComponent<{}, {}, any>;
export default component;
}
This is also the solution taken in the Vue 3 Codesandbox playground and also suggested by Vetur docs.
Hey everyone,
I tried import a Component class inside a .ts file, a mixin. In .vue's files import occurs normal, no error in VsCode, but import inside a .ts's file the erro show up. Adding a ts-shim file with *.vue declaration, the error gone, but I lose CTRL +
Any one have a better solution?
Version
2.2.6
Reproduction link
https://github.com/borislitvak/vue-from-vue-question
Steps to reproduce
I've asked on stackoverflow and vue forum, no answer for several days. I am new to client side development.
What is expected?
I can import the MyTable.vue into App.vue. Both components are writting in Typescript.
NOTE: I can import the TS vue component into another TS file, i.e., App.vue into example.ts.
What is actually happening?
During webpack build:
ERROR in ....\App.vue.ts (20,24): error TS2307: Cannot find module './MyTable.vue'.
https://forum.vuejs.org/t/how-can-i-view-vue-loader-logs-and-generated-files/8350 http://stackoverflow.com/questions/42945415/import-vue-module-from-another-vue-module-in-typescript