diff --git a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/slot-typechecks/diagnostics-slots-imported.svelte b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/slot-typechecks/diagnostics-slots-imported.svelte
index 2e7530a2c..f5e414741 100644
--- a/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/slot-typechecks/diagnostics-slots-imported.svelte
+++ b/packages/language-server/test/plugins/typescript/features/diagnostics/fixtures/slot-typechecks/diagnostics-slots-imported.svelte
@@ -2,8 +2,10 @@
export let prop: any;
const defaultSlotProp = 1;
const namedSlotProp = true;
+ const spread = {a: true, b: ''};
{prop}
+ {a === true} + {c === ''} + {a === ''} + {d} +
diff --git a/packages/svelte2tsx/src/svelte2tsx/createRenderFunction.ts b/packages/svelte2tsx/src/svelte2tsx/createRenderFunction.ts index d24cbf995..b663d8f52 100644 --- a/packages/svelte2tsx/src/svelte2tsx/createRenderFunction.ts +++ b/packages/svelte2tsx/src/svelte2tsx/createRenderFunction.ts @@ -88,7 +88,11 @@ export function createRenderFunction({ Array.from(slots.entries()) .map(([name, attrs]) => { const attrsAsString = Array.from(attrs.entries()) - .map(([exportName, expr]) => `${exportName}:${expr}`) + .map(([exportName, expr]) => + exportName.startsWith('__spread__') + ? `...${expr}` + : `${exportName}:${expr}` + ) .join(', '); return `'${name}': {${attrsAsString}}`; }) diff --git a/packages/svelte2tsx/src/svelte2tsx/nodes/slot.ts b/packages/svelte2tsx/src/svelte2tsx/nodes/slot.ts index 4cd6f1301..3ef5b650f 100644 --- a/packages/svelte2tsx/src/svelte2tsx/nodes/slot.ts +++ b/packages/svelte2tsx/src/svelte2tsx/nodes/slot.ts @@ -61,6 +61,12 @@ export class SlotHandler { return resolved; } + /** + * Returns a string which expresses the given identifier unpacked to + * the top level in order to express the slot types correctly later on. + * + * Example: {#each items as item} ---> __sveltets_1_unwrapArr(items) + */ private getResolveExpressionStr( identifierDef: SvelteIdentifier, scope: TemplateScope, @@ -168,6 +174,10 @@ export class SlotHandler { })); } + /** + * Resolves the slot expression to a string that can be used + * in the props-object in the return type of the render function + */ private resolveExpression(expression: Node, scope: TemplateScope) { let resolved = this.resolvedExpression.get(expression); if (resolved) { @@ -234,6 +244,14 @@ export class SlotHandler { if (attr.name == 'name') { continue; } + + if (attr.type === 'Spread') { + const rawName = attr.expression.name; + const init = scope.getInit(rawName); + const name = init ? this.resolved.get(init) : rawName; + attributes.set(`__spread__${name}`, name); + } + if (!attr.value?.length) { continue; } @@ -268,6 +286,7 @@ export class SlotHandler { if (attrVal.type == 'MustacheTag') { return this.resolveExpression(attrVal.expression, scope); } + throw Error('Unknown attribute value type:' + attrVal.type); } } diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-object-key/expected.tsx b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-object-key/expected.tsx index f1218a3d8..7ab845809 100644 --- a/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-object-key/expected.tsx +++ b/packages/svelte2tsx/test/svelte2tsx/samples/component-slot-object-key/expected.tsx @@ -2,9 +2,9 @@ <>>;function render() { /*Ωignore_startΩ*/;const __sveltets_ensureSlot = __sveltets_1_createEnsureSlot();/*Ωignore_endΩ*/ <>{__sveltets_1_each(items, (item) => <> -