Subscribe on changes!

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

avatar
Feb 7th 2021

Version

3.0.5

Reproduction link

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

Steps to reproduce

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'

avatar
Feb 7th 2021

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.

avatar
Feb 7th 2021
avatar
Feb 7th 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:

https://github.com/vuejs/rfcs/pull/227#issuecomment-766427503

avatar
Feb 7th 2021

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.

avatar
Feb 7th 2021

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?

avatar
Feb 7th 2021

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

Agree

avatar
Mar 2nd 2021

This workaround breaks eslint-prettier, so weird.

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.

avatar
Mar 2nd 2021

how exaxctly? I use eslint and prettier fine with this.

avatar
Mar 8th 2021

@LinusBorg The problem is I didn't install prettier as dependency. (I thought that eslint-plugin-prettier has the dependency) Everything is okay right now, sorry for that.

avatar
Mar 10th 2021

I rethinked this with https://github.com/vuejs/vue-next/issues/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

avatar
Mar 12th 2021

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'
avatar
Apr 10th 2021

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.

avatar
Jul 2nd 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 🤔)

avatar
Jul 22nd 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.