PropType is ignored in Vue files with `<script setup>`
Hi, when we create our component as SFC and use script setup Vite Plugin DTS just ignores type and uses ArrayConstructor ObjectConstructor like types, not the ones we specified.
But in normal vue file without script setup it correct d.ts file but not 100% accurate.
You can see built types in dist/types folder created from src folder. https://github.com/kadiryazici/vite-plugin-dts-issue
Script Setup One
Component code:
<script lang="ts">
export interface Props {
items: { text: string }[];
}
export default {
name: 'TheListeleme',
};
</script>
<script lang="ts" setup>
withDefaults(defineProps<Props>(), {
items: () => [],
});
</script>
<template>
<ul>
<li
v-for="item in items"
:key="item.text"
>
{{ item.text }}
</li>
</ul>
{{ 5 }}
</template>
Generated d.ts code, look at line 7 it says ArrayConstructor
export interface Props {
items: {
text: string;
}[];
}
declare const _sfc_main: import("vue").DefineComponent<{
items: {
type: ArrayConstructor;
required: true;
default: () => any[];
};
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
items: {
type: ArrayConstructor;
required: true;
default: () => any[];
};
}>>, {
items: unknown[];
}>;
export default _sfc_main;
With normal setup
Component code:
<script lang="ts">
import { defineComponent, type PropType } from 'vue';
type Item = { text: string };
export interface Props {
items: Item[];
}
export default defineComponent({
name: 'TheListeleme',
props: {
items: {
type: Array as PropType<Props['items']>,
default: () => [],
},
},
});
</script>
<template>
<ul>
<li
v-for="item in items"
:key="item.text"
>
{{ item.text }}
</li>
</ul>
{{ 5 }}
</template>
DTS code:
- This time types are accurate but approach is different, instead of
Props['items']it just usesItem[], not the same as source code.
import { type PropType } from 'vue';
declare type Item = {
text: string;
};
export interface Props {
items: Item[];
}
declare const _sfc_main: import("vue").DefineComponent<{
items: {
type: PropType<Item[]>;
default: () => any[];
};
}, unknown, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
items: {
type: PropType<Item[]>;
default: () => any[];
};
}>>, {
items: Item[];
}>;
export default _sfc_main;
With TS file
Component code:
import { h, defineComponent, type PropType, renderList } from 'vue';
interface Props {
items: { text: string }[];
}
export default defineComponent({
name: 'TheListeleme',
props: {
items: {
type: Array as PropType<Props['items']>,
default: () => [],
},
},
setup(props) {
return () =>
h(
'ul',
null,
renderList(props.items, (item) => h('li', {}, item.text)),
);
},
});
DTS Code:
- It gets rid of Props here again
import { type PropType } from 'vue';
export interface Props {
items: {
text: string;
}[];
}
declare const _default: import("vue").DefineComponent<{
items: {
type: PropType<{
text: string;
}[]>;
default: () => any[];
};
}, () => JSX.Element, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
items: {
type: PropType<{
text: string;
}[]>;
default: () => any[];
};
}>>, {
items: {
text: string;
}[];
}>;
export default _default;
It needs to use the js way to define props, and the ts way will not be able to infer types after the compiler compiled.
vue-tsc is able create correct, maybe that behavior can be injectable?
I tried building the first example with up-to-date vite-plugin-dts, Vue & Vite and got:
import type { PropType as __PropType } from 'vue';
export interface Props {
items: {
text: string;
}[];
}
declare const _sfc_main: import("vue").DefineComponent<{
items: {
type: __PropType<{
text: string;
}[]>;
required: true;
default: () => never[];
};
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
items: {
type: __PropType<{
text: string;
}[]>;
required: true;
default: () => never[];
};
}>>, {
items: {
text: string;
}[];
}>;
export default _sfc_main;
Perhaps something has changed somewhere else that fixes this?
Fxied.