Typescript issue with importing type from vue
Vue version
3.3.4
Link to minimal reproduction
https://github.com/tragid/vue-default-export-error
Steps to reproduce
I'm trying to build a Button component using Typescript and utilizing types of HTML element imported from Vue package. Here is the code:
import type { ButtonHTMLAttributes, LinkHTMLAttributes } from 'vue'
import type { RouterLinkProps } from 'vue-router'
type ButtonOrAnchorProps = BaseProps & ButtonHTMLAttributes & LinkHTMLAttributes
type ButtonAsRouterLink = BaseProps & RouterLinkProps & LinkHTMLAttributes
type ButtonProps = ButtonAsRouterLink | ButtonOrAnchorProps
const props = defineProps<ButtonProps>()
What is expected?
The type should be imported normally without any error.
What is actually happening?
Vue throws error:
[@vue/compiler-sfc] Unresolvable type reference or unsupported built-in utility type
It's kind of strange because I can still access the attributes from props
variable like props.href
but the app is not running.
What I tried is to create alternative types that extend ButtonHTMLAttributes
and LinkHTMLAttributes
, it's like:
import { type ButtonHTMLAttributes, type LinkHTMLAttributes } from 'vue'
export interface BtnHTMLAttr extends /* @vue-ignore */ ButtonHTMLAttributes {}
export interface LinkHTMLAttr extends /* @vue-ignore */ LinkHTMLAttributes {}
The import error is gone but the app is still not functioning properly. When I add a href
prop to the component, seems like the component doesn't recognize href
prop
System Info
No response
Any additional comments?
No response
Hi, thanks for your reply.
For some reasons, I cannot get the href
props even if I pass it in parent component. Here is my code for Button component:
<script setup lang="ts">
import clsx from 'clsx'
import type { ButtonHTMLAttributes, LinkHTMLAttributes } from 'vue'
// Here is tailwind class for variants
const variants = {
primary: 'bg-blue-600 text-white hover:bg-gray-50:text-blue-600',
secondary: 'bg-gray-200 text-black-300 hover:bg-blue-600:text-white'
}
interface BaseProps {
variant?: keyof typeof variants
}
interface ButtonAsButton
extends /* @vue-ignore */ BaseProps,
/* @vue-ignore */ ButtonHTMLAttributes {}
interface ButtonAsLink extends /* @vue-ignore */ BaseProps, /* @vue-ignore */ LinkHTMLAttributes {}
type ButtonProps = ButtonAsButton | ButtonAsLink
const props = withDefaults(defineProps<ButtonProps>(), {
variant: 'primary'
})
// Here you can add style from tailwind, below is the demo
const className = clsx(
'flex items-center justify-center px-4 py-2 rounded font-medium focus:outline-none',
variants[props.variant],
props.class
)
const newProps = { ...props }
newProps.class = className
let As = 'button'
if ('href' in newProps) {
As = 'a'
}
if (As === 'button') {
newProps['type'] = newProps.type ? newProps.type : 'button'
}
</script>
<template>
<As v-bind="newProps"><slot></slot></As>
</template>
<style scoped></style>
And I pass the href
prop like: <VButton href="dsadsad">fdss</VButton>
However, href
isn't recognized. What is the problem?