Skip to content
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

script-setup: Types need to be imported separately with import type .... #3183

Closed
JSerFeng opened this issue Feb 7, 2021 · 15 comments
Closed
Labels
has workaround A workaround has been found to avoid the problem scope: script-setup scope: sfc ✨ feature request New feature or request

Comments

@JSerFeng
Copy link

JSerFeng commented Feb 7, 2021

Version

3.0.5

Reproduction link

https://github.com/JSerFeng/bug/blob/master/src/App.vue

Steps to reproduce

<script setup lang="ts"> import {Ref} from "vue" </script>

What is expected?

nothing happens

What is actually happening?

Uncaught SyntaxError: The requested module '/node_modules/.vite/vue.js?v=6cc5afeb' does not provide an export named 'Ref'

@LinusBorg
Copy link
Member

It's a Bug in the compiler that doesn't differentiate between type exports and runtime exports.

As a workaround, you can use import type { Ref } from 'vue' to import types explicitly as types.

@LinusBorg LinusBorg added 🐞 bug Something isn't working scope: script-setup has workaround A workaround has been found to avoid the problem labels Feb 7, 2021
@HcySunYang
Copy link
Member

Is it related to vite? vitejs/vite#1661

@LinusBorg
Copy link
Member

LinusBorg commented Feb 7, 2021

Don't think so, that issue revolved around runtime exports (unref, openBlock).

There were also comments about the problem with Type exports in the RFC comments that found the same solution/workaround:

vuejs/rfcs#227 (comment)

@HcySunYang
Copy link
Member

Oh, the code it generates looks like this:

import {Ref} from 'vue'

export default {
  expose: [],
  setup(__props) {
    return { Ref }
  }
}

But I can't find any way other than list all types through enumeration, or we can consider imports beginning with capital letters as types, but exclude such things as Teleport/ErrorCodes.

@LinusBorg
Copy link
Member

Yeah, don't think that would be a reliable heuristic. I don't think the compiler can reliably determine wether or not an import is a Type or a runtime object, so in theory we would have to clean up the imports with Ts somehow before generating the code.

No idea if something like this is even feasable, not really familiar enough with compiler details.

Should we consider this an enhancement rather than a bug as import type works for now, and the RFC is still in flux?

@HcySunYang
Copy link
Member

Should we consider this an enhancement rather than a bug as import type works for now, and the RFC is still in flux?

Agree

@LinusBorg LinusBorg added ✨ feature request New feature or request and removed 🐞 bug Something isn't working labels Feb 7, 2021
@LinusBorg LinusBorg changed the title type "Ref" is not exported from "vue" when use script setup script-setup: Types need to be imported separately with import type .... Feb 7, 2021
@yoyoys

This comment has been minimized.

@LinusBorg

This comment has been minimized.

@yoyoys

This comment has been minimized.

@HcySunYang
Copy link
Member

I rethinked this with #3249. Why do we need to expose the imports from vue? maybe it was a mistake? I know that build-in components must be exposed, like Teleport:

<script setup>
import { Teleport } from 'vue'
</script>

output:

export default {
  expose: [],
  setup() {
    return { Teleport }
  }
}

So we only need a whitelist: Teleport, Transition, TransitionGroup, KeepAlive, Suspense

@Blackfaded
Copy link

For Types the import type solution worked for me. But I cant get interfaces working. I always get the warning, that the interface is not exported.

"export 'Consultation' was not found in '@/libs/shared/interfaces/consultation'

@johnsoncodehk
Copy link
Member

I think compiler has no a perfect way to solve this problem, but IDE already report error for this use case, so maybe we don't need to do anything in compiler side.

@jods4
Copy link
Contributor

jods4 commented Jul 2, 2021

This impacts types, which you can work-around by using import type; and const enums, which you can't work around in a practical way (both import and import type create errors, in different places).

One solution to this problem could be to check what is actually used by the template and not export identifiers that it doesn't use.

  • Not sure if that would fully work with HMR?
  • It's more work as it would require analyzing the globals of every expression in template, but at least it's a local solution to the problem (i.e. no need to do cross-files type analysis to figure out what is a type).
  • It only partially solves the const enum problem: now you can import them and use them in code, but you still can't use them in template.

I believe none of this is an issue when building for production and the template becomes a lambda inside the setup code, which simply has local scope automatically captured.

That's actually great and the best solution, the only issue is that the other way is used in dev to enable HMR / exposing state to dev tools. I wonder if we could figure out a way to do those things with the lambda design instead... (I don't have an idea just yet 🤔)

@jods4
Copy link
Contributor

jods4 commented Jul 22, 2021

@yyx990803 it's fantastic you could fix that!
On top of what was already said above, it really messed up with VS Code auto-complete.
When you try to auto-import a type, VS Code always adds it to an existing plain import and you must go back and manually split things in two imports.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
has workaround A workaround has been found to avoid the problem scope: script-setup scope: sfc ✨ feature request New feature or request
Projects
None yet
Development

No branches or pull requests

9 participants