Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add generics support
  • Loading branch information
minht11 committed Nov 5, 2023
commit a0d1d9bcb2513d492d3032d582c6c08aba4c2ae6
2 changes: 1 addition & 1 deletion .changeset/two-oranges-knock.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
'@astrojs/vue': minor
---

Add editor support for Vue non setup script blocks.
Add editor support for Vue non setup script blocks and Vue 3.3 generics.
20 changes: 12 additions & 8 deletions packages/integrations/vue/src/editor.cts
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,27 @@ export function toTSX(code: string, className: string): string {

// Vue supports 2 type of script blocks: setup and non-setup
const regularScriptBlockContent = parsedResult.descriptor.script?.content ?? '';
const { scriptSetup } = parsedResult.descriptor;

if (parsedResult.descriptor.scriptSetup) {
const definePropsType =
parsedResult.descriptor.scriptSetup.content.match(/defineProps<([\s\S]+)>/m);
if (scriptSetup) {
const definePropsType = scriptSetup.content.match(/defineProps<([\S\s]+?)>\s?\(\)/m);
const propsGeneric = scriptSetup.attrs.generic;
const propsGenericType = propsGeneric ? `<${propsGeneric}>` : '';

if (definePropsType) {
result = `
${regularScriptBlockContent}
${parsedResult.descriptor.scriptSetup.content}
${scriptSetup.content}

export default function ${className}__AstroComponent_(_props: ${definePropsType[1]}): any {
export default function ${className}__AstroComponent_${propsGenericType}(_props: ${definePropsType[1]}): any {
<div></div>
}
`;
} else {
const defineProps =
parsedResult.descriptor.scriptSetup.content.match(/defineProps\([\s\S]+\)/m);
// TODO. Find a way to support generics when using defineProps without passing explicit types.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ultimately, this module shouldn't use a regex to get the types, it should use something like https://github.com/vuejs/language-tools/tree/master/packages/component-meta and https://github.com/vuejs/language-tools/tree/master/packages/component-type-helpers

which should support everything (or at least, if it doesn't, would be a bug upstream that's not in our hands)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I have looked briefly into these packages after I opened this PR and its not so far I haven't found an easy way.

component-meta gives narrows prop types and output loses generic information, so T extends string becomes just string.

component-type-helpers needs a component instance types, to import which requires vue language server I think and still it loses all generic information and narrows types. I am not sure how would that work with virtual file.

Current approach is not sustainable and prone to fail, right now astro doesn't account for https://vuejs.org/guide/typescript/composition-api.html#props-default-values or experimental defineModel and so on and yet I am not sure how to get something better in a short term.

// Right now something like this `defineProps({ prop: { type: Array as PropType<T[]> } })`
// won't be correctly typed in Astro.
const defineProps = scriptSetup.content.match(/defineProps\([\s\S]+\)/m);

if (defineProps) {
result = `
Expand All @@ -46,7 +50,7 @@ export function toTSX(code: string, className: string): string {

const Props = ${defineProps[0]}

export default function ${className}__AstroComponent_(_props: typeof Props): any {
export default function ${className}__AstroComponent_${propsGenericType}(_props: typeof Props): any {
<div></div>
}
`;
Expand Down