From 259ff2c85d193681ace45dd681678ef25581b5c7 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 27 Feb 2024 17:32:12 +0100 Subject: [PATCH] fix: don't add form types when not typed out people could have a `+page.svelte` that hasn't any actions --- .../src/svelte2tsx/nodes/ExportedNames.ts | 174 +++++++++--------- 1 file changed, 88 insertions(+), 86 deletions(-) diff --git a/packages/svelte2tsx/src/svelte2tsx/nodes/ExportedNames.ts b/packages/svelte2tsx/src/svelte2tsx/nodes/ExportedNames.ts index 2f1e60b4d..634b78afb 100644 --- a/packages/svelte2tsx/src/svelte2tsx/nodes/ExportedNames.ts +++ b/packages/svelte2tsx/src/svelte2tsx/nodes/ExportedNames.ts @@ -228,99 +228,101 @@ export class ExportedNames { return; } - if (internalHelpers.isKitRouteFile(this.basename)) { - this.$props.mayHaveChildrenProp = this.basename.includes('layout'); - const kitType = this.$props.mayHaveChildrenProp - ? `{ data: import('./$types.js').LayoutData, form: import('./$types.js').ActionData, children: import('svelte').Snippet }` - : `{ data: import('./$types.js').PageData, form: import('./$types.js').ActionData }`; - - if (this.isTsFile) { - this.$props.generic = kitType; - preprendStr( - this.str, - node.initializer.expression.end + this.astOffset, - surroundWithIgnoreComments(`<${kitType}>`) - ); - } else { - this.$props.comment = `/** @type {${kitType}} */`; - preprendStr(this.str, node.pos + this.astOffset, this.$props.comment); - } - } else { - // Do a best-effort to extract the props from the object literal - let propsStr = ''; - let withUnknown = false; - let props = []; - - if (ts.isObjectBindingPattern(node.name)) { - for (const element of node.name.elements) { - if ( - !ts.isIdentifier(element.name) || - (element.propertyName && !ts.isIdentifier(element.propertyName)) || - !!element.dotDotDotToken - ) { - withUnknown = true; - } else { - const name = element.propertyName - ? (element.propertyName as ts.Identifier).text - : element.name.text; - if (element.initializer) { - const type = ts.isAsExpression(element.initializer) - ? element.initializer.type.getText() - : ts.isStringLiteral(element.initializer) - ? 'string' - : ts.isNumericLiteral(element.initializer) - ? 'number' - : element.initializer.kind === ts.SyntaxKind.TrueKeyword || - element.initializer.kind === ts.SyntaxKind.FalseKeyword - ? 'boolean' - : ts.isIdentifier(element.initializer) - ? `typeof ${element.initializer.text}` - : 'unknown'; - props.push(`${name}?: ${type}`); - } else { - props.push(`${name}: unknown`); + // Do a best-effort to extract the props from the object literal + let propsStr = ''; + let withUnknown = false; + let props = []; + + const isKitRouteFile = internalHelpers.isKitRouteFile(this.basename); + const isKitLayoutFile = isKitRouteFile && this.basename.includes('layout'); + if (isKitRouteFile) { + this.$props.mayHaveChildrenProp = isKitLayoutFile; + } + + if (ts.isObjectBindingPattern(node.name)) { + for (const element of node.name.elements) { + if ( + !ts.isIdentifier(element.name) || + (element.propertyName && !ts.isIdentifier(element.propertyName)) || + !!element.dotDotDotToken + ) { + withUnknown = true; + } else { + const name = element.propertyName + ? (element.propertyName as ts.Identifier).text + : element.name.text; + if (isKitRouteFile) { + if (name === 'data') { + props.push( + `data: import('./$types.js').${ + isKitLayoutFile ? 'LayoutData' : 'PageData' + }` + ); } + if (name === 'form' && !isKitLayoutFile) { + props.push(`form: import('./$types.js').ActionData`); + } + } else if (element.initializer) { + const type = ts.isAsExpression(element.initializer) + ? element.initializer.type.getText() + : ts.isStringLiteral(element.initializer) + ? 'string' + : ts.isNumericLiteral(element.initializer) + ? 'number' + : element.initializer.kind === ts.SyntaxKind.TrueKeyword || + element.initializer.kind === ts.SyntaxKind.FalseKeyword + ? 'boolean' + : ts.isIdentifier(element.initializer) + ? `typeof ${element.initializer.text}` + : 'unknown'; + props.push(`${name}?: ${type}`); + } else { + props.push(`${name}: unknown`); } } + } - if (props.length > 0) { - propsStr = - `{ ${props.join(', ')} }` + - (withUnknown ? ' & Record' : ''); - } else if (withUnknown) { - propsStr = 'Record'; - } else { - propsStr = 'Record'; - } - } else { - propsStr = 'Record'; + if (isKitLayoutFile) { + props.push(`children: import('svelte').Snippet`); } - // Create a virtual type alias for the unnamed generic and reuse it for the props return type - // so that rename, find references etc works seamlessly across components - if (this.isTsFile) { - this.$props.generic = '$$_sveltets_Props'; - if (props.length > 0 || withUnknown) { - preprendStr( - this.str, - node.parent.pos + this.astOffset, - surroundWithIgnoreComments(`;type $$_sveltets_Props = ${propsStr};`) - ); - preprendStr( - this.str, - node.initializer.expression.end + this.astOffset, - `<${this.$props.generic}>` - ); - } + if (props.length > 0) { + propsStr = + `{ ${props.join(', ')} }` + + (withUnknown ? ' & Record' : ''); + } else if (withUnknown) { + propsStr = 'Record'; } else { - this.$props.comment = '/** @type {$$_sveltets_Props} */'; - if (props.length > 0 || withUnknown) { - preprendStr( - this.str, - node.pos + this.astOffset, - `/** @typedef {${propsStr}} $$_sveltets_Props */${this.$props.comment}` - ); - } + propsStr = 'Record'; + } + } else { + propsStr = 'Record'; + } + + // Create a virtual type alias for the unnamed generic and reuse it for the props return type + // so that rename, find references etc works seamlessly across components + if (this.isTsFile) { + this.$props.generic = '$$_sveltets_Props'; + if (props.length > 0 || withUnknown) { + preprendStr( + this.str, + node.parent.pos + this.astOffset, + surroundWithIgnoreComments(`;type $$_sveltets_Props = ${propsStr};`) + ); + preprendStr( + this.str, + node.initializer.expression.end + this.astOffset, + `<${this.$props.generic}>` + ); + } + } else { + this.$props.comment = '/** @type {$$_sveltets_Props} */'; + if (props.length > 0 || withUnknown) { + preprendStr( + this.str, + node.pos + this.astOffset, + `/** @typedef {${propsStr}} $$_sveltets_Props */${this.$props.comment}` + ); } } }