Skip to content

Commit 259ff2c

Browse files
committed
fix: don't add form types when not typed out
people could have a `+page.svelte` that hasn't any actions
1 parent 6badc2f commit 259ff2c

File tree

1 file changed

+88
-86
lines changed

1 file changed

+88
-86
lines changed

packages/svelte2tsx/src/svelte2tsx/nodes/ExportedNames.ts

Lines changed: 88 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -228,99 +228,101 @@ export class ExportedNames {
228228
return;
229229
}
230230

231-
if (internalHelpers.isKitRouteFile(this.basename)) {
232-
this.$props.mayHaveChildrenProp = this.basename.includes('layout');
233-
const kitType = this.$props.mayHaveChildrenProp
234-
? `{ data: import('./$types.js').LayoutData, form: import('./$types.js').ActionData, children: import('svelte').Snippet }`
235-
: `{ data: import('./$types.js').PageData, form: import('./$types.js').ActionData }`;
236-
237-
if (this.isTsFile) {
238-
this.$props.generic = kitType;
239-
preprendStr(
240-
this.str,
241-
node.initializer.expression.end + this.astOffset,
242-
surroundWithIgnoreComments(`<${kitType}>`)
243-
);
244-
} else {
245-
this.$props.comment = `/** @type {${kitType}} */`;
246-
preprendStr(this.str, node.pos + this.astOffset, this.$props.comment);
247-
}
248-
} else {
249-
// Do a best-effort to extract the props from the object literal
250-
let propsStr = '';
251-
let withUnknown = false;
252-
let props = [];
253-
254-
if (ts.isObjectBindingPattern(node.name)) {
255-
for (const element of node.name.elements) {
256-
if (
257-
!ts.isIdentifier(element.name) ||
258-
(element.propertyName && !ts.isIdentifier(element.propertyName)) ||
259-
!!element.dotDotDotToken
260-
) {
261-
withUnknown = true;
262-
} else {
263-
const name = element.propertyName
264-
? (element.propertyName as ts.Identifier).text
265-
: element.name.text;
266-
if (element.initializer) {
267-
const type = ts.isAsExpression(element.initializer)
268-
? element.initializer.type.getText()
269-
: ts.isStringLiteral(element.initializer)
270-
? 'string'
271-
: ts.isNumericLiteral(element.initializer)
272-
? 'number'
273-
: element.initializer.kind === ts.SyntaxKind.TrueKeyword ||
274-
element.initializer.kind === ts.SyntaxKind.FalseKeyword
275-
? 'boolean'
276-
: ts.isIdentifier(element.initializer)
277-
? `typeof ${element.initializer.text}`
278-
: 'unknown';
279-
props.push(`${name}?: ${type}`);
280-
} else {
281-
props.push(`${name}: unknown`);
231+
// Do a best-effort to extract the props from the object literal
232+
let propsStr = '';
233+
let withUnknown = false;
234+
let props = [];
235+
236+
const isKitRouteFile = internalHelpers.isKitRouteFile(this.basename);
237+
const isKitLayoutFile = isKitRouteFile && this.basename.includes('layout');
238+
if (isKitRouteFile) {
239+
this.$props.mayHaveChildrenProp = isKitLayoutFile;
240+
}
241+
242+
if (ts.isObjectBindingPattern(node.name)) {
243+
for (const element of node.name.elements) {
244+
if (
245+
!ts.isIdentifier(element.name) ||
246+
(element.propertyName && !ts.isIdentifier(element.propertyName)) ||
247+
!!element.dotDotDotToken
248+
) {
249+
withUnknown = true;
250+
} else {
251+
const name = element.propertyName
252+
? (element.propertyName as ts.Identifier).text
253+
: element.name.text;
254+
if (isKitRouteFile) {
255+
if (name === 'data') {
256+
props.push(
257+
`data: import('./$types.js').${
258+
isKitLayoutFile ? 'LayoutData' : 'PageData'
259+
}`
260+
);
282261
}
262+
if (name === 'form' && !isKitLayoutFile) {
263+
props.push(`form: import('./$types.js').ActionData`);
264+
}
265+
} else if (element.initializer) {
266+
const type = ts.isAsExpression(element.initializer)
267+
? element.initializer.type.getText()
268+
: ts.isStringLiteral(element.initializer)
269+
? 'string'
270+
: ts.isNumericLiteral(element.initializer)
271+
? 'number'
272+
: element.initializer.kind === ts.SyntaxKind.TrueKeyword ||
273+
element.initializer.kind === ts.SyntaxKind.FalseKeyword
274+
? 'boolean'
275+
: ts.isIdentifier(element.initializer)
276+
? `typeof ${element.initializer.text}`
277+
: 'unknown';
278+
props.push(`${name}?: ${type}`);
279+
} else {
280+
props.push(`${name}: unknown`);
283281
}
284282
}
283+
}
285284

286-
if (props.length > 0) {
287-
propsStr =
288-
`{ ${props.join(', ')} }` +
289-
(withUnknown ? ' & Record<string, unknown>' : '');
290-
} else if (withUnknown) {
291-
propsStr = 'Record<string, unknown>';
292-
} else {
293-
propsStr = 'Record<string, never>';
294-
}
295-
} else {
296-
propsStr = 'Record<string, unknown>';
285+
if (isKitLayoutFile) {
286+
props.push(`children: import('svelte').Snippet`);
297287
}
298288

299-
// Create a virtual type alias for the unnamed generic and reuse it for the props return type
300-
// so that rename, find references etc works seamlessly across components
301-
if (this.isTsFile) {
302-
this.$props.generic = '$$_sveltets_Props';
303-
if (props.length > 0 || withUnknown) {
304-
preprendStr(
305-
this.str,
306-
node.parent.pos + this.astOffset,
307-
surroundWithIgnoreComments(`;type $$_sveltets_Props = ${propsStr};`)
308-
);
309-
preprendStr(
310-
this.str,
311-
node.initializer.expression.end + this.astOffset,
312-
`<${this.$props.generic}>`
313-
);
314-
}
289+
if (props.length > 0) {
290+
propsStr =
291+
`{ ${props.join(', ')} }` +
292+
(withUnknown ? ' & Record<string, unknown>' : '');
293+
} else if (withUnknown) {
294+
propsStr = 'Record<string, unknown>';
315295
} else {
316-
this.$props.comment = '/** @type {$$_sveltets_Props} */';
317-
if (props.length > 0 || withUnknown) {
318-
preprendStr(
319-
this.str,
320-
node.pos + this.astOffset,
321-
`/** @typedef {${propsStr}} $$_sveltets_Props */${this.$props.comment}`
322-
);
323-
}
296+
propsStr = 'Record<string, never>';
297+
}
298+
} else {
299+
propsStr = 'Record<string, unknown>';
300+
}
301+
302+
// Create a virtual type alias for the unnamed generic and reuse it for the props return type
303+
// so that rename, find references etc works seamlessly across components
304+
if (this.isTsFile) {
305+
this.$props.generic = '$$_sveltets_Props';
306+
if (props.length > 0 || withUnknown) {
307+
preprendStr(
308+
this.str,
309+
node.parent.pos + this.astOffset,
310+
surroundWithIgnoreComments(`;type $$_sveltets_Props = ${propsStr};`)
311+
);
312+
preprendStr(
313+
this.str,
314+
node.initializer.expression.end + this.astOffset,
315+
`<${this.$props.generic}>`
316+
);
317+
}
318+
} else {
319+
this.$props.comment = '/** @type {$$_sveltets_Props} */';
320+
if (props.length > 0 || withUnknown) {
321+
preprendStr(
322+
this.str,
323+
node.pos + this.astOffset,
324+
`/** @typedef {${propsStr}} $$_sveltets_Props */${this.$props.comment}`
325+
);
324326
}
325327
}
326328
}

0 commit comments

Comments
 (0)