Skip to content

Adding generic= to <script setup> makes it impossible to export types from SFC #13410

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

Open
alexchexes opened this issue May 29, 2025 · 3 comments
Labels
language-tools related to vue language-tools scope: types

Comments

@alexchexes
Copy link

Vue version

3.5.16

Link to minimal reproduction

https://github.com/alexchexes/vue-test-generic-export/blob/master/src/App.vue

Steps to reproduce

  1. Add generic="T" attribute to the <script setup> (<script setup lang="ts" generic="T">)
  2. Add a type export, e.g. export type MyType = 123, within that script setup scope
  3. Observe the Modifiers cannot appear here. ts(1184) TypeScript error in VSCode
  4. Remove generic="T" and the error disappears, confirming the issue is related to the generic="T" attribute

Reproduction:

<script setup lang="ts" generic="T">
defineProps<{
  items: string[]
  selected: string
}>()
export type MyType = 123 // ← TS Error: Modifiers cannot appear here. ts(1184)
</script>

What is expected?

No error should occur when exporting types after adding generic="T" to <script setup>

What is actually happening?

A Modifiers cannot appear here. ts(1184) TypeScript error appears as soon as generic="T" is added to <script setup>, but no error occurs when it is removed

System Info

System:
    OS: Windows 11 10.0.26100
    CPU: (20) x64 12th Gen Intel(R) Core(TM) i7-12700H
    Memory: 32.97 GB / 63.67 GB
  Binaries:
    Node: 22.11.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.22 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 10.9.0 - C:\Program Files\nodejs\npm.CMD
    pnpm: 9.12.3 - ~\AppData\Roaming\npm\pnpm.CMD
  Browsers:
    Edge: Chromium (130.0.2849.80)
  npmPackages:
    vue: ^3.5.13 => 3.5.16

Any additional comments?

If this is a restriction of generic components, we should mention it in the generics section of the <script setup> docs

@edison1105 edison1105 added scope: types language-tools related to vue language-tools labels May 30, 2025
@KazariEX
Copy link
Member

KazariEX commented Jun 2, 2025

When we use generic, we should assume that all the code in the script block is within the scope of the function.

You can move the type declarations with export modifier to the top to avoid this situation.

@alexchexes
Copy link
Author

alexchexes commented Jun 2, 2025

You can move the type declarations with export modifier to the top to avoid this situation

Unlike the code in the example, in the real code the use case is to export the type of whatever emit() returns. I mean something like this (real code):

const emit = defineEmits<{
  /** emitted in case of any error (usually only network errors occurs) */
  'error': [error: unknown];
  /** emitted after suggestion is selected, whether by clicking on a suggestion in the dropdown, by pressing "Enter" or by auto-selecting when `selectOnBlur=true` */
  'select': [suggestion: DadataSuggestion, selectType: SelectType];
  /** emitted after selected suggestion was enriched in case `enrichOnSelect` props is `true` */
  'enriched': [suggestion: DadataSuggestion, diff: DeepPartial<DadataSuggestion> | null];
  /** emitted if attemp to enrich selected suggestion failed (in case `enrichOnSelect` props is `true`) */
  'enrichFail': [unrestricted_value: string];
  /** emitted whenever input is focused */
  'focus': [event: FocusEvent];
  /** emitted whenever input looses focus */
  'blur': [event: FocusEvent];
}>();
export type VueDadataEmits = typeof emit;

So we can pass emit to the composable and emit from there without using any any.
What is the recommended approach in this case?

@KazariEX
Copy link
Member

KazariEX commented Jun 2, 2025

Firstly, ensure that the type of the emit is independent of generic type parameters; Then it is best to use some type helpers to explicitly infer the type of emit in a non setup script block and export it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
language-tools related to vue language-tools scope: types
Projects
None yet
Development

No branches or pull requests

3 participants