diff --git a/packages/svelte2tsx/src/svelte2tsx/nodes/ExportedNames.ts b/packages/svelte2tsx/src/svelte2tsx/nodes/ExportedNames.ts index c01098d63..e4b05eaf4 100644 --- a/packages/svelte2tsx/src/svelte2tsx/nodes/ExportedNames.ts +++ b/packages/svelte2tsx/src/svelte2tsx/nodes/ExportedNames.ts @@ -277,22 +277,33 @@ export class ExportedNames { 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}` - : ts.isObjectLiteralExpression(element.initializer) - ? 'Record' - : ts.isArrayLiteralExpression(element.initializer) - ? 'unknown[]' - : 'unknown'; + const initializer = + ts.isCallExpression(element.initializer) && + ts.isIdentifier(element.initializer.expression) && + element.initializer.expression.text === '$bindable' + ? element.initializer.arguments[0] + : element.initializer; + const type = !initializer + ? 'unknown' + : ts.isAsExpression(initializer) + ? initializer.type.getText() + : ts.isStringLiteral(initializer) + ? 'string' + : ts.isNumericLiteral(initializer) + ? 'number' + : initializer.kind === ts.SyntaxKind.TrueKeyword || + initializer.kind === ts.SyntaxKind.FalseKeyword + ? 'boolean' + : ts.isIdentifier(initializer) && + initializer.text !== 'undefined' + ? `typeof ${initializer.text}` + : ts.isArrowFunction(initializer) + ? 'Function' + : ts.isObjectLiteralExpression(initializer) + ? 'Record' + : ts.isArrayLiteralExpression(initializer) + ? 'unknown[]' + : 'unknown'; props.push(`${name}?: ${type}`); } else { props.push(`${name}: unknown`); diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/runes-best-effort-types.v5/expectedv2.ts b/packages/svelte2tsx/test/svelte2tsx/samples/runes-best-effort-types.v5/expectedv2.ts index 7947bc2b2..7404a44ab 100644 --- a/packages/svelte2tsx/test/svelte2tsx/samples/runes-best-effort-types.v5/expectedv2.ts +++ b/packages/svelte2tsx/test/svelte2tsx/samples/runes-best-effort-types.v5/expectedv2.ts @@ -1,10 +1,10 @@ /// ;function render() { - let/** @typedef {{ a: unknown, b?: boolean, c?: number, d?: string, e?: unknown, f?: Record, g?: typeof foo, h?: unknown[] }} $$ComponentProps *//** @type {$$ComponentProps} */ { a, b = true, c = 1, d = '', e = null, f = {}, g = foo, h = [] } = $props(); + let/** @typedef {{ a: unknown, b?: boolean, c?: number, d?: string, e?: unknown, f?: Record, g?: typeof foo, h?: unknown[], i?: unknown, j?: unknown, k?: number, l?: Function }} $$ComponentProps *//** @type {$$ComponentProps} */ { a, b = true, c = 1, d = '', e = null, f = {}, g = foo, h = [], i = undefined, j = $bindable(), k = $bindable(1), l = () => {} } = $props(); ; async () => {}; -return { props: /** @type {$$ComponentProps} */({}), exports: {}, bindings: __sveltets_$$bindings(''), slots: {}, events: {} }} +return { props: /** @type {$$ComponentProps} */({}), exports: {}, bindings: __sveltets_$$bindings('j', 'k'), slots: {}, events: {} }} const Input__SvelteComponent_ = __sveltets_2_fn_component(render()); type Input__SvelteComponent_ = ReturnType; export default Input__SvelteComponent_; \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/runes-best-effort-types.v5/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/runes-best-effort-types.v5/input.svelte index b4dc7f14b..73baf2a20 100644 --- a/packages/svelte2tsx/test/svelte2tsx/samples/runes-best-effort-types.v5/input.svelte +++ b/packages/svelte2tsx/test/svelte2tsx/samples/runes-best-effort-types.v5/input.svelte @@ -1,3 +1,3 @@ diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-best-effort-types.v5/expectedv2.ts b/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-best-effort-types.v5/expectedv2.ts index 6f830be1c..455e1b9b6 100644 --- a/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-best-effort-types.v5/expectedv2.ts +++ b/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-best-effort-types.v5/expectedv2.ts @@ -1,10 +1,10 @@ /// ;function render() { -/*Ωignore_startΩ*/;type $$ComponentProps = { a: unknown, b?: boolean, c?: number, d?: string, e?: unknown, f?: Record, g?: typeof foo, h?: Bar, i?: Baz, j?: unknown[] };/*Ωignore_endΩ*/ - let { a, b = true, c = 1, d = '', e = null, f = {}, g = foo, h = null as Bar, i = null as any as Baz, j = [] }: $$ComponentProps = $props(); +/*Ωignore_startΩ*/;type $$ComponentProps = { a: unknown, b?: boolean, c?: number, d?: string, e?: unknown, f?: Record, g?: typeof foo, h?: Bar, i?: Baz, j?: unknown[], k?: unknown, l?: unknown, m?: number, n?: Function };/*Ωignore_endΩ*/ + let { a, b = true, c = 1, d = '', e = null, f = {}, g = foo, h = null as Bar, i = null as any as Baz, j = [], k = undefined, l = $bindable(), m = $bindable(1), n = () => {} }: $$ComponentProps = $props(); ; async () => {}; -return { props: {} as any as $$ComponentProps, exports: {}, bindings: __sveltets_$$bindings(''), slots: {}, events: {} }} +return { props: {} as any as $$ComponentProps, exports: {}, bindings: __sveltets_$$bindings('l', 'm'), slots: {}, events: {} }} const Input__SvelteComponent_ = __sveltets_2_fn_component(render()); type Input__SvelteComponent_ = ReturnType; export default Input__SvelteComponent_; \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-best-effort-types.v5/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-best-effort-types.v5/input.svelte index cda8c476f..c4ce94411 100644 --- a/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-best-effort-types.v5/input.svelte +++ b/packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-best-effort-types.v5/input.svelte @@ -1,3 +1,3 @@