Accessing generically typed props in <script lang='ts' setup> causes transform failure
Vue version
3.2.38
Link to minimal reproduction
Steps to reproduce
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>
I also created a repo more like my use case here
What is expected?
Have access to the component's props
What is actually happening?
An error is thrown:
[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
System Info
System:
OS: macOS 12.6
CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
Memory: 21.29 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:
vue: ^3.2.38 => 3.2.40