Skip to content

Commit e90ea65

Browse files
authored
fix(language-core): avoid using __typeProps with runtime props (#4800)
1 parent 858d7c4 commit e90ea65

File tree

2 files changed

+52
-30
lines changed
  • packages/language-core/lib/codegen/script
  • test-workspace/tsc/passedFixtures/vue3/#4799

2 files changed

+52
-30
lines changed

packages/language-core/lib/codegen/script/component.ts

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ export function* generateEmitsOption(
6565
scriptSetupRanges: ScriptSetupRanges
6666
): Generator<Code> {
6767
const codes: {
68+
// undefined means the emit source cannot be explained by expression
6869
optionExp?: Code,
70+
// undefined means the emit source cannot be explained by type
6971
typeOptionType?: Code,
7072
}[] = [];
7173
if (scriptSetupRanges.defineProp.some(p => p.isModel)) {
@@ -125,21 +127,29 @@ export function* generatePropsOption(
125127
hasEmitsOption: boolean,
126128
inheritAttrs: boolean
127129
): Generator<Code> {
128-
const optionExpCodes: Code[] = [];
129-
const typeOptionExpCodes: Code[] = [];
130+
const codes: {
131+
optionExp: Code,
132+
// undefined means the prop source cannot be explained by type
133+
typeOptionExp?: Code,
134+
}[] = [];
130135

131136
if (ctx.generatedPropsType) {
132-
optionExpCodes.push([
133-
`{} as `,
134-
scriptSetupRanges.props.withDefaults?.arg ? `${ctx.localTypes.WithDefaults}<` : '',
135-
`${ctx.localTypes.TypePropsToOption}<__VLS_PublicProps>`,
136-
scriptSetupRanges.props.withDefaults?.arg ? `, typeof __VLS_withDefaultsArg>` : '',
137-
].join(''));
138-
typeOptionExpCodes.push(`{} as __VLS_PublicProps`);
137+
codes.push({
138+
optionExp: [
139+
`{} as `,
140+
scriptSetupRanges.props.withDefaults?.arg ? `${ctx.localTypes.WithDefaults}<` : '',
141+
`${ctx.localTypes.TypePropsToOption}<__VLS_PublicProps>`,
142+
scriptSetupRanges.props.withDefaults?.arg ? `, typeof __VLS_withDefaultsArg>` : '',
143+
].join(''),
144+
typeOptionExp: `{} as __VLS_PublicProps`,
145+
});
139146
}
140147
if (scriptSetupRanges.props.define?.arg) {
141148
const { arg } = scriptSetupRanges.props.define;
142-
optionExpCodes.push(generateSfcBlockSection(scriptSetup, arg.start, arg.end, codeFeatures.navigation));
149+
codes.push({
150+
optionExp: generateSfcBlockSection(scriptSetup, arg.start, arg.end, codeFeatures.navigation),
151+
typeOptionExp: undefined,
152+
});
143153
}
144154
if (inheritAttrs && options.templateCodegen?.inheritedAttrVars.size) {
145155
let attrsType = `__VLS_TemplateResult['attrs']`;
@@ -148,46 +158,45 @@ export function* generatePropsOption(
148158
}
149159
const propsType = `__VLS_PickNotAny<${ctx.localTypes.OmitIndexSignature}<${attrsType}>, {}>`;
150160
const optionType = `${ctx.localTypes.TypePropsToOption}<${propsType}>`;
151-
if (optionExpCodes.length) {
152-
optionExpCodes.unshift(`{} as ${optionType}`);
153-
}
154-
else {
155-
// workaround for https://github.com/vuejs/core/pull/7419
156-
optionExpCodes.unshift(`{} as keyof ${propsType} extends never ? never: ${optionType}`);
157-
}
158-
typeOptionExpCodes.unshift(`{} as ${attrsType}`);
161+
codes.unshift({
162+
optionExp: codes.length
163+
? `{} as ${optionType}`
164+
// workaround for https://github.com/vuejs/core/pull/7419
165+
: `{} as keyof ${propsType} extends never ? never: ${optionType}`,
166+
typeOptionExp: `{} as ${attrsType}`,
167+
});
159168
}
160169

161-
const useTypeOption = options.vueCompilerOptions.target >= 3.5 && typeOptionExpCodes.length;
162-
const useOption = (!useTypeOption || scriptSetupRanges.props.withDefaults) && optionExpCodes.length;
170+
const useTypeOption = options.vueCompilerOptions.target >= 3.5 && codes.every(code => code.typeOptionExp);
171+
const useOption = !useTypeOption || scriptSetupRanges.props.withDefaults;
163172

164173
if (useTypeOption) {
165-
if (typeOptionExpCodes.length === 1) {
174+
if (codes.length === 1) {
166175
yield `__typeProps: `;
167-
yield typeOptionExpCodes[0];
176+
yield codes[0].typeOptionExp!;
168177
yield `,${newLine}`;
169178
}
170-
else if (typeOptionExpCodes.length >= 2) {
179+
else if (codes.length >= 2) {
171180
yield `__typeProps: {${newLine}`;
172-
for (const code of typeOptionExpCodes) {
181+
for (const { typeOptionExp } of codes) {
173182
yield `...`;
174-
yield code;
183+
yield typeOptionExp!;
175184
yield `,${newLine}`;
176185
}
177186
yield `},${newLine}`;
178187
}
179188
}
180189
if (useOption) {
181-
if (optionExpCodes.length === 1) {
190+
if (codes.length === 1) {
182191
yield `props: `;
183-
yield optionExpCodes[0];
192+
yield codes[0].optionExp;
184193
yield `,${newLine}`;
185194
}
186-
else if (optionExpCodes.length >= 2) {
195+
else if (codes.length >= 2) {
187196
yield `props: {${newLine}`;
188-
for (const code of optionExpCodes) {
197+
for (const { optionExp } of codes) {
189198
yield `...`;
190-
yield code;
199+
yield optionExp;
191200
yield `,${newLine}`;
192201
}
193202
yield `},${newLine}`;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<script lang="ts" setup>
2+
import { exactType } from '../../shared';
3+
4+
defineProps({
5+
foo: String
6+
});
7+
8+
defineModel();
9+
</script>
10+
11+
<template>
12+
{{ exactType(foo, {} as string | undefined) }}
13+
</template>

0 commit comments

Comments
 (0)