-
-
Notifications
You must be signed in to change notification settings - Fork 243
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
Support <script setup /> in vue 3 #676
Conversation
In Vue 3, when <script> tag has "setup" attribute, SFC parser assigned script block to a separate field called "scriptSetup" ✅ Closes: #668
I am not an expert but I need these updates so I gave it a shot at testing it locally. It seems that it does not recognize that I have The good news is that it now checks Test1.vue <script lang="ts">
import { defineComponent } from 'vue'
const test: boolean = "test"
export default defineComponent({
data() {
return {
test
}
}
})
</script>
<template>
<div>
{{ test }}
</div>
</template> Test2.vue <script setup lang="ts">
const test: boolean = "true"
const props = defineProps({
prop1: String,
})
</script>
<template>
<div>
{{ test }}
</div>
</template> The bad news is that regular components are no longer handled correctly. ERROR in src/Test1.vue:5:7
TS2322: Type '"test"' is not assignable to type 'boolean'.
3 | <script lang="ts">
4 | import { defineComponent } from 'vue'
> 5 | const test: boolean = "test"
| ^^^^
6 | export default defineComponent({
7 | data() {
8 | return {
ERROR in src/Test1.vue:7:3
TS2769: No overload matches this call.
The last overload gave the following error.
Argument of type '{ data(): { test: boolean; }; }' is not assignable to parameter ofown, unknown, {}, {}, ComponentOptionsMixin, ... 4 more ..., any>'.
Object literal may only specify known properties, and 'data' does not exist in typ unknown, {}, {}, ComponentOptionsMixin, ... 4 more ..., any>'.
5 | const test: boolean = "test"
6 | export default defineComponent({
> 7 | data() {
| ^^^^
8 | return {
9 | test
10 | }
ERROR in src/Test2.vue:3:7
TS2322: Type '"true"' is not assignable to type 'boolean'.
1 |
2 | <script setup lang="ts">
> 3 | const test: boolean = "true"
| ^^^^
4 | const props = defineProps({
5 | prop1: String,
6 | })
webpack 5.64.1 compiled with 3 errors in 1249 ms Compared to the output of ERROR in src/Test1.vue:5:7
3 | <script lang="ts">
4 | import { defineComponent } from 'vue'
> 5 | const test: boolean = "test"
| ^^^^
6 | export default defineComponent({
7 | data() {
8 | return {
webpack 5.64.1 compiled with 1 error in 1460 ms Edit ERROR in src/Test1.vue:7:3
TS2769: No overload matches this call.
The last overload gave the following error.
Argument of type '{ data(): { test: boolean; }; }' is not assignable to parameter of type 'ComponentOptionsWithObjectProps<readonly string[] | Readonly<ComponentObjectPropsOptions<Record<string, unknown>>>, unknown, unknown, {}, {}, ComponentOptionsMixin, ... 4 more ..., any>'.
Object literal may only specify known properties, and 'data' does not exist in type 'ComponentOptionsWithObjectProps<readonly string[] | Readonly<ComponentObjectPropsOptions<Record<string, unknown>>>, unknown, unknown, {}, {}, ComponentOptionsMixin, ... 4 more ..., any>'.
5 | const test: boolean = false
6 | export default defineComponent({
> 7 | data() {
| ^^^^
8 | return {
9 | test
10 | }
ERROR in src/Test2.vue:3:7
TS2322: Type '"true"' is not assignable to type 'boolean'.
1 |
2 | <script setup lang="ts">
> 3 | const test: boolean = "true"
| ^^^^
4 | const props = defineProps({
5 | prop1: String,
6 | })
webpack 5.64.1 compiled with 2 errors in 1269 ms |
@filimon-danopoulos-stratsys thanks for testing! I will add a test-case with |
I had to use Luckily I don’t have any legacy component, but I do have the situation where I have both a
Now in another component I try to import that interface, but get the error:
|
@piotr-oles Packing and installing locally fixes the issue I encountered. Just another case of |
@bodograumann I can verify that this is indeed an issue. In addition, no type checking is performed in Test3.vue <script setup lang="ts">
const test: boolean = 'test'
</script>
<script lang="ts">
const test: boolean = 'test'
export interface TestInterface {
prop1: string
}
</script>
<template>
<div>
{{ test }}
</div>
</template> I simply import it and use it for ERROR in src/Test1.vue:5:7
TS2322: Type 'string' is not assignable to type 'boolean'.
3 | <script lang="ts">
4 | import { defineComponent } from 'vue'
> 5 | const test: boolean = "test"
| ^^^^
6 | export default defineComponent({
7 | data() {
8 | return {
ERROR in src/Test2.vue:3:10
TS2614: Module '"./Test3.vue"' has no exported member 'TestInterface'. Did you mean to use 'import TestInterface from "./Test3.vue"' instead?
1 |
2 | <script setup lang="ts">
> 3 | import { TestInterface } from "./Test3.vue"
| ^^^^^^^^^^^^^
4 |
5 | const test: boolean = "true"
6 | const props = defineProps<TestInterface>()
ERROR in src/Test2.vue:5:7
TS2322: Type 'string' is not assignable to type 'boolean'.
3 | import { TestInterface } from "./Test3.vue"
4 |
> 5 | const test: boolean = "true"
| ^^^^
6 | const props = defineProps<TestInterface>()
7 | </script>
8 |
ERROR in src/Test3.vue:12:7
TS2322: Type 'string' is not assignable to type 'boolean'.
10 |
11 | <script setup lang="ts">
> 12 | const test: boolean = 'test'
| ^^^^
13 | </script>
14 |
15 | <template>
webpack 5.64.1 compiled with 4 errors in 1569 ms The Note that I am not using it through |
Is it correct to have |
Yes it is valid, see https://v3.vuejs.org/api/sfc-script-setup.html#usage-alongside-normal-script |
Thanks, I will try to support for this case :) |
I pushed a new commit with support for |
Works nicely, thank you @piotr-oles. Hopefully we can get this into vue-cli soon. |
🎉 This PR is included in version 6.4.1 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Unfortunately it does not work 100%. The following does not typescheck <script setup lang="ts">
const test1: boolean = 'test1'
</script>
<script lang="ts">
const test2: boolean = 'test2'
export interface TestInterface {
prop1: string
}
</script>
<template>
<div>
{{ test }}
</div>
</template> Result ERROR in src/Test2.vue:5:7
TS2322: Type 'string' is not assignable to type 'boolean'.
3 | import { TestInterface } from "./Test3.vue"
4 |
> 5 | const test: boolean = "true"
| ^^^^
6 | const props = defineProps<TestInterface>()
7 | </script>
8 |
ERROR in src/Test3.vue:7:7
TS2322: Type 'string' is not assignable to type 'boolean'.
5 |
6 | <script lang="ts">
> 7 | const test2: boolean = 'test2'
| ^^^^^
8 | export interface TestInterface {
9 | prop1: string
10 | }
webpack 5.64.2 compiled with 3 errors in 1546 ms I would have expected to see an error for {
"script": [
"//",
"//",
"//",
"//",
"//",
"",
"const test: boolean = 'test2'",
"export interface TestInterface {",
" prop1: string",
"}",
""
],
"setup": [
"//",
"",
"const test: boolean = 'test1'",
""
],
"merge": [
"//",
"//",
"//",
"//",
"//",
null,
"const test: boolean = 'test2'",
"export interface TestInterface {",
" prop1: string",
"}",
null
]
} This means that you would never get the contents of the Furthermore I am not certain that this approach will result in correct behavior. Type checking both these things together might produce type warnings that are not valid. <script setup>
const test = "test"
</script> Is in practice something like this (the actually generated code is different, this just illustrates the point) import { defineComponent } from 'vue'
export default defineComponent({
setup() {
const test = "test"
return {
test
}
}
}) Expanding that example with a regular <script>
const test = "test"
</script>
<script setup>
const test = "test"
</script> Would generate something like this import { defineComponent } from 'vue'
const test = "test"
export default defineComponent({
setup() {
const test = "test"
return {
test
}
}
}) Where the two constants both named const test = "test"
const test = "test" The two |
Has anyone encountered this error? "vue": "2.6.11",
"vue-template-compiler": "2.6.11"
"@vue/composition-api": "1.2.4", <template>
<div id="app">
hello world
</div>
</template>
<script setup lang="ts">
const x: string = 42;
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
}
</style> Error File '/Users/xxx/cli5-test/src/App.vue.ts' is not a module.
1 | import Vue from 'vue'
> 2 | import App from './App.vue' my declare module '*.vue' {
import Vue from 'vue'
export default Vue
} |
@screetBloom You cannot use |
This reverts commit 40e4ecf.
I would suggest you use the provided API from @johnsoncodehk that he mentioned here as he seems to have solved these issues already. |
Actually, you can, with https://github.com/antfu/unplugin-vue2-script-setup |
It's not that easy to integrate as it seems :) I will have to add source-map support to the plugin to properly map diagnostic positions. |
If you need, I can expose volar internal source map api. It can transform between source range and generated range. |
Sorry I don't think that I can be of much assistance in the implementation. I don't know the codebase well enough to provide meaningful feedback. Am happy to test it when there is something to look at again. |
🎉 This PR is included in version 7.0.0-alpha.15 🎉 The release is available on: Your semantic-release bot 📦🚀 |
In Vue 3, when <script> tag has "setup" attribute, SFC parser assignes script block to a separate field called "scriptSetup"
It's a second attempt to handle this syntax, the previous one was reverted due to incomplete feature support (#668).
See #668, #665