Skip to content

Commit

Permalink
fix(language-core): avoid using __typeProps with runtime props (#4800)
Browse files Browse the repository at this point in the history
  • Loading branch information
KazariEX authored Sep 4, 2024
1 parent 858d7c4 commit e90ea65
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 30 deletions.
69 changes: 39 additions & 30 deletions packages/language-core/lib/codegen/script/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ export function* generateEmitsOption(
scriptSetupRanges: ScriptSetupRanges
): Generator<Code> {
const codes: {
// undefined means the emit source cannot be explained by expression
optionExp?: Code,
// undefined means the emit source cannot be explained by type
typeOptionType?: Code,
}[] = [];
if (scriptSetupRanges.defineProp.some(p => p.isModel)) {
Expand Down Expand Up @@ -125,21 +127,29 @@ export function* generatePropsOption(
hasEmitsOption: boolean,
inheritAttrs: boolean
): Generator<Code> {
const optionExpCodes: Code[] = [];
const typeOptionExpCodes: Code[] = [];
const codes: {
optionExp: Code,
// undefined means the prop source cannot be explained by type
typeOptionExp?: Code,
}[] = [];

if (ctx.generatedPropsType) {
optionExpCodes.push([
`{} as `,
scriptSetupRanges.props.withDefaults?.arg ? `${ctx.localTypes.WithDefaults}<` : '',
`${ctx.localTypes.TypePropsToOption}<__VLS_PublicProps>`,
scriptSetupRanges.props.withDefaults?.arg ? `, typeof __VLS_withDefaultsArg>` : '',
].join(''));
typeOptionExpCodes.push(`{} as __VLS_PublicProps`);
codes.push({
optionExp: [
`{} as `,
scriptSetupRanges.props.withDefaults?.arg ? `${ctx.localTypes.WithDefaults}<` : '',
`${ctx.localTypes.TypePropsToOption}<__VLS_PublicProps>`,
scriptSetupRanges.props.withDefaults?.arg ? `, typeof __VLS_withDefaultsArg>` : '',
].join(''),
typeOptionExp: `{} as __VLS_PublicProps`,
});
}
if (scriptSetupRanges.props.define?.arg) {
const { arg } = scriptSetupRanges.props.define;
optionExpCodes.push(generateSfcBlockSection(scriptSetup, arg.start, arg.end, codeFeatures.navigation));
codes.push({
optionExp: generateSfcBlockSection(scriptSetup, arg.start, arg.end, codeFeatures.navigation),
typeOptionExp: undefined,
});
}
if (inheritAttrs && options.templateCodegen?.inheritedAttrVars.size) {
let attrsType = `__VLS_TemplateResult['attrs']`;
Expand All @@ -148,46 +158,45 @@ export function* generatePropsOption(
}
const propsType = `__VLS_PickNotAny<${ctx.localTypes.OmitIndexSignature}<${attrsType}>, {}>`;
const optionType = `${ctx.localTypes.TypePropsToOption}<${propsType}>`;
if (optionExpCodes.length) {
optionExpCodes.unshift(`{} as ${optionType}`);
}
else {
// workaround for https://github.com/vuejs/core/pull/7419
optionExpCodes.unshift(`{} as keyof ${propsType} extends never ? never: ${optionType}`);
}
typeOptionExpCodes.unshift(`{} as ${attrsType}`);
codes.unshift({
optionExp: codes.length
? `{} as ${optionType}`
// workaround for https://github.com/vuejs/core/pull/7419
: `{} as keyof ${propsType} extends never ? never: ${optionType}`,
typeOptionExp: `{} as ${attrsType}`,
});
}

const useTypeOption = options.vueCompilerOptions.target >= 3.5 && typeOptionExpCodes.length;
const useOption = (!useTypeOption || scriptSetupRanges.props.withDefaults) && optionExpCodes.length;
const useTypeOption = options.vueCompilerOptions.target >= 3.5 && codes.every(code => code.typeOptionExp);
const useOption = !useTypeOption || scriptSetupRanges.props.withDefaults;

if (useTypeOption) {
if (typeOptionExpCodes.length === 1) {
if (codes.length === 1) {
yield `__typeProps: `;
yield typeOptionExpCodes[0];
yield codes[0].typeOptionExp!;
yield `,${newLine}`;
}
else if (typeOptionExpCodes.length >= 2) {
else if (codes.length >= 2) {
yield `__typeProps: {${newLine}`;
for (const code of typeOptionExpCodes) {
for (const { typeOptionExp } of codes) {
yield `...`;
yield code;
yield typeOptionExp!;
yield `,${newLine}`;
}
yield `},${newLine}`;
}
}
if (useOption) {
if (optionExpCodes.length === 1) {
if (codes.length === 1) {
yield `props: `;
yield optionExpCodes[0];
yield codes[0].optionExp;
yield `,${newLine}`;
}
else if (optionExpCodes.length >= 2) {
else if (codes.length >= 2) {
yield `props: {${newLine}`;
for (const code of optionExpCodes) {
for (const { optionExp } of codes) {
yield `...`;
yield code;
yield optionExp;
yield `,${newLine}`;
}
yield `},${newLine}`;
Expand Down
13 changes: 13 additions & 0 deletions test-workspace/tsc/passedFixtures/vue3/#4799/main.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<script lang="ts" setup>
import { exactType } from '../../shared';
defineProps({
foo: String
});
defineModel();
</script>

<template>
{{ exactType(foo, {} as string | undefined) }}
</template>

0 comments on commit e90ea65

Please sign in to comment.