Skip to content

[vue3] - Accessing generically typed props in <script lang='ts' setup> causes transform failure. #10304

@joemaylor

Description

@joemaylor

Describe the bug

Firstly, apologies if it seems like this should be an issue in the Vue 3 repo. I can move it across if that's the case.

I am trying to create a reusable Vue 3 component with generically typed props.
Let's say I want a props interface that looks something like:

// ChildComponent.vue
interface MyProps<T> {
  propOne: T
  propTwo: () => Array<T>
}

The goal of this is so that something like the below would fail:

// ParentComponent.vue
<template>
  <!-- 5 is a number, but "foo" and "bar" are strings 👎  -->
  <child-component
    :prop-one="5"
    :prop-two="() => ["foo", "bar"]"
  />
</template

Using this example, and also running into this issue I came up with the following:

// ChildComponent.vue
<script setup lang="ts">
defineProps<MyChildProps<unknown>>()
</script>

<script lang="ts">
export interface MyChildProps<T> {
  propOne: T
  propTwo: () => Array<T>
}
</script>

<template>
  <div>{{ propOne }}</div>
</template>
// ChildComponentWithGenerics.vue
<script lang="ts">
import ChildComponent from './ChildComponent.vue'
import type { MyChildProps } from './ChildComponent.vue'

type ChildComponentWithGenerics = new <T>(props: MyChildProps<T>) => {
  $props: MyChildProps<T>
}

export default ChildComponent as ChildComponentWithGenerics
</script>

This successfully results in the following:

// ParentComponent.vue
<script setup lang="ts">
const getSomeStrings = () => ["foo", "bar"]
</script>

<template>
  <!-- 5 is a number, but "foo" and "bar" are strings 👎  -->
  <child-component
    :prop-one="5"
    :prop-two="getSomeStrings"
  />

  <!-- this is fine! 👍  -->
  <child-component
    prop-one="vite rocks!"
    :prop-two="getSomeStrings"
  />
</template>

Great, all working fine. That is, until I try and access the props in ChildComponent.vue...
As soon as I add const props = to then do some logic with the props, I get an error.

// ChildComponent.vue
<script setup lang="ts">

// accessing the props here causes the error ❌
const props = defineProps<MyChildProps<unknown>>()
</script>

<script lang="ts">
export interface MyChildProps<T> {
  propOne: T
  propTwo: () => Array<T>
}
</script>

<template>
  <div>{{ propOne }}</div>
</template>

The error I get is the following:

[plugin:vite:vue] Transform failed with 1 error:
/Users/josephmaylor/Desktop/vite-project/src/components/ChildComponent.vue:18:41: ERROR: Unexpected ")"

/Users/josephmaylor/Desktop/vite-project/src/components/ChildComponent.vue:18:41

Unexpected ")"
16 | expose();
17 |
18 | const props = __props as Props>()
| ^
19 |
20 |

at failureErrorWithLog (/Users/josephmaylor/Desktop/vite-project/node_modules/.pnpm/esbuild@0.15.10/node_modules/esbuild/lib/main.js:1566:15)
at /Users/josephmaylor/Desktop/vite-project/node_modules/.pnpm/esbuild@0.15.10/node_modules/esbuild/lib/main.js:805:29
at responseCallbacks. (/Users/josephmaylor/Desktop/vite-project/node_modules/.pnpm/esbuild@0.15.10/node_modules/esbuild/lib/main.js:671:9)
at handleIncomingPacket (/Users/josephmaylor/Desktop/vite-project/node_modules/.pnpm/esbuild@0.15.10/node_modules/esbuild/lib/main.js:726:9)
at Socket.readFromStdout (/Users/josephmaylor/Desktop/vite-project/node_modules/.pnpm/esbuild@0.15.10/node_modules/esbuild/lib/main.js:647:7)
at Socket.emit (node:events:526:28)
at addChunk (node:internal/streams/readable:315:12)
at readableAddChunk (node:internal/streams/readable:289:9)
at Socket.Readable.push (node:internal/streams/readable:228:10)
at Pipe.onStreamRead (node:internal/stream_base_commons:190:23

Reproduction

https://github.com/joemaylor/type-generic-props-repro

System Info

  System:
    OS: macOS 12.6
    CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 25.54 MB / 16.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 16.14.2 - /usr/local/bin/node
    Yarn: 1.22.10 - /usr/local/bin/yarn
    npm: 8.5.0 - /usr/local/bin/npm
  Browsers:
    Chrome: 106.0.5249.91
    Firefox: 105.0.1
    Safari: 16.0
  npmPackages:
    @vitejs/plugin-vue: ^3.0.3 => 3.1.0 
    vite: ^3.0.9 => 3.1.4 

Used Package Manager

pnpm

Logs

No response

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug: upstreamBug in a dependency of Vite

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions