-
Notifications
You must be signed in to change notification settings - Fork 918
Unable to use TypeScript type exports from vue component file #1281
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Vue files currently does not support type exports, because that's processed at the TypeScript checker level, and all /cc @octref |
@yyx990803 I forgot to mention, webpack will build properly on incremental build. So after the error is shown on initial build, if you then just touch the file I don't understand enough of the internal build process to know if this is useful information or not, but just wanted to point it out in case. |
An unrelated opinion: I think we should put the below code in a separate ts file. because it's purely model mode. export type MessageType = 'none' | 'info' | 'warning' | 'error' | 'success' | 'loading'
export interface Message {
type: MessageType
dismissable: boolean
content: string
} and I prefer declare a enum type for export enum MessageType{
none = 'none',
info = 'info' ,
warning = 'warning',
error = 'success' ,
loading = 'loading',
} |
As @yyx990803 said there is no existing way to do this. Your best bet right now would be having a @DanielRosenwasser Do you know what would it take to have this supported in TS? microsoft/TypeScript#12846 doesn't seem to cover it. |
Really, you need something special to resolve these types correctly within
There's always been a problem with importing from I've forgotten whether the Webpack loaders are capable of doing "the right thing" without the |
Could this way help you ? //index.ts
You can just write your template and styles in .vue file (and it is surport //Template.vue
//test.ts
//in ohter .ts to import
You can use ts type now; @yyx990803 @dakaraphi |
@nailfar yes, it has been worked around using .ts files. It is just not as convenient. |
We can write a bash or node script to create module files.
// vue Template
// barrel Template
{{FILE_NAME}} will be replaced by the script; |
@nailfar This will make the hot update not work |
This is the two methods I tried, but there are still problems. And a another way: file list
import components from './Hello.vue';
import componentsClass from './Hello.script';
class Magic extends componentsClass {}
(<any>Magic) = components;
export default Magic; This is written using |
@yyx990803 It is probably a good idea to allow vue-loader to use the ts file as an entry point. about (I have been exploring vue + typescript and if there is a chance I hope we can talk about it.) |
I found a more appropriate method. (TypeStrong/ts-loader#826 (comment)) We only need to spoof the IDE's language service to achieve the goal. For example: Demonstrates Repository: https://github.com/ZSkycat/issue-ts-loader-20180829/tree/better Hello.vue
Hello.vue.ts
Used in ts file
The most important thing is the naming of the ts file.
|
@dakaraphi The real problem is that you should not reexport type here. Exporting type in vue file is fine. More technical detail: Vue loader depends on ts-loader to transpile script. And ts-loader in turn requires vue-loader to extract script from vue file. Communication between two loaders are done via webpack: vue-loader will generate script files like At first build, vue-loader hasn't generated script. To kick off the generation, vue-loader has to first ask ts-loader for script content to find out all components in the build. Thus, ts-loader transpiles script independently without other files' info in the first run because vue files aren't processed yet. But in later build type checking works because script generation has done before. However, re-exporting type requires type info and cannot be transpiled solely by one single file. My recommendation is to turn on As @yyx990803 said, vue-loader cannot do much here. So this issue can be safely closed since exporting type actually works . Supporting re-exporting type isn't widely supported in JS community and I suspect its value. |
There is a workaround with default objects. // Type intended to share between vue components
type MyCommonType = {
id?:string,
name:string,
}
export const MyDefaultProp:MyCommonType = {
id:'',
name:'',
} // component1.vue . . .
import {MyDefaultProp} from './types.ts'
type MyPropType = typeof MyDefaultProp // Better than defining whole type/interface
export default class Component1 extends Vue {
@Prop({ default: () => Object.assign({}, MyDefaultProp), type: Object }) myProp!: MyPropType
. . . // component2.vue . . .
import {MyDefaultProp} from './types.ts'
type MyPropType = typeof MyDefaultProp // Better than defining whole type/interface
export default class Component2 extends Vue {
@Prop({ default: () => Object.assign({}, MyDefaultProp), type: Object }) myProp!: MyPropType
. . . Typescript compiler will be happy without any warning... |
I am gonna import ts file in vue component. |
Is there some problems with this solution ? I tried it on some components seems ok but why this is not preferred way then ? |
@rene-dohan I would say doing it that way defeats the purpose of single file components. It's fine if you want to split it your code to work around this issue but many do not. A separate type definitions file is much more palatable as that is pretty common in Typescript land. |
这问题有任何进展吗?或者在将来的vue 3中是否能解决,如果不,那么vue,sfc文件的地位可能不保,按照composition api和jsx的方式开展开发,可能是vue 3的最佳方向。但这意味着,这跟react已经很贴近了。 |
Maybe you came from React or Angular world, but I cannot imagine having components separated into many different files in my project. For me Vuejs is the best because just one single file component and a proper HTML, not tsx ugly monster. So I can focus on bringing new features instead of messing around with huge amount of different files and parts and types. I have a working solution but sometimes it is not working as expected in bigger projects. I think if we try to push this solution to vuejs/webpack/typescript developers, it might end our pain.
<template>
<div>{{ test }}</div>
</template>
<script lang="ts">
import Vue from "vue";
export default Vue.extend({
data() {
return {
test: "abc"
};
},
methods: {
reverse(): void {
this.test = "cba";
}
}
});
</script>
<style lang="scss" scoped>
div { background: $primaryBgColor; }
</style>
<template>
<div>
<MyComponent ref="myComponent" />
<input type="button" value="Click me" @click="onClick">
</div>
</template>
<script lang="ts">
import Vue from "vue";
import MyComponent from "./MyComponent.vue";
type MyComponentType = InstanceType<typeof MyComponent>;
export default Vue.extend({
components: {
MyComponent
},
data() {
return {
};
},
methods: {
onClick(): void {
(this.$refs.myComponent as MyComponentType).reverse(); // Compiling with no errors
(this.$refs.myComponent as MyComponentType).reverse2(); // Error: 'reverse2' does not exist
}
}
});
</script> You can find the working sample here: https://github.com/fairking/vuetstest What do you think guys? |
Interestingly, in my testing with the latest Vue CLI, I can indeed export a type from a My current "workaround" is to just have the types in an accompanying |
@vincerubinetti This is because the Vue tooling is aware of the Vue SFCs, but the Typescript tooling is not, which is why each project has a |
I would love to see this get resolved, otherwise I have to keep some component members (types, enums) in a separate file somewhere else. Certainly not the biggest issue in the world, but results in degraded code organization. |
Hi, was wondering if there is a common suffix that has been converged on, for the "code behind" file that is needed for this. i.e., |
I came here looking for solution, albeit I'm using Vite, not Webpack. In the case someone comes with the same question, here's the solution:
|
Version
15.0.0
Reproduction link
https://github.com/dakaraphi/vue-loader-bug-sample
Steps to reproduce
What is expected?
Should build without error
What is actually happening?
16:77-84 "export 'Message' was not found in './InlineMessage.vue'
This seems related to #1234
The text was updated successfully, but these errors were encountered: