Skip to content

svelte-kit sync types generation overlooks destructured exports #16326

Description

@celskeggs

Describe the bug

Specifying a load function as an ordinary constant allows SvelteKit to derive the proper type for data:

// In +page.server.ts
export const load = async () => ({value: 10});
// In +page.svelte
<script lang="ts"> let { data } = $props(); </script>
<p>Value = {data.value}</p>

But defining the same constant using destructuring results in the type getting misdefined, resulting in a typechecking error on {data.value}:

export const { load } = { load: async () => ({value: 10}) };

I believe this is likely caused by the following snippet of code, which only works if declaration.name is an Identifier. In this case, it is an ObjectBindingPattern instead:

if (ts.isVariableStatement(node)) {
node.declarationList.declarations.forEach((declaration) => {
if (ts.isIdentifier(declaration.name) && names.has(declaration.name.text)) {
exports.set(declaration.name.text, declaration.name.text);
}
});
}
:

Reproduction

$ git clone https://github.com/celskeggs/object-binding-exports/
$ cd object-binding-exports
$ npm install
$ npm run check

Logs

$ npm run check

> object-binding-exports@0.0.1 check
> svelte-kit sync && svelte-check --tsconfig ./tsconfig.json

Loading svelte-check in workspace: /[...]/object-binding-exports
Getting Svelte diagnostics...

/[...]/object-binding-exports/src/routes/+page.svelte:2:18
Error: Property 'value' does not exist on type '{}'. (ts)
<script lang="ts"> let { data } = $props(); </script>
<p>Value = {data.value}</p>

====================================
svelte-check found 1 error and 0 warnings in 1 file

System Info

System:
    OS: Linux 6.1 Debian GNU/Linux 12 (bookworm) 12 (bookworm)
    CPU: (16) x64 AMD Ryzen 7 PRO 5850U with Radeon Graphics
    Memory: 2.98 GB / 14.46 GB
    Container: Yes
    Shell: 5.2.15 - /bin/bash
  Binaries:
    Node: 20.20.0 - /[...]/.nvm/versions/node/v20.20.0/bin/node
    Yarn: 1.22.22 - /[...]/.nvm/versions/node/v20.20.0/bin/yarn
    npm: 10.8.2 - /[...]/.nvm/versions/node/v20.20.0/bin/npm
  Browsers:
    Chromium: 150.0.7871.46
    Firefox: 140.12.0esr
    Firefox Developer Edition: 140.12.0esr
  npmPackages:
    @sveltejs/adapter-auto: ^7.0.1 => 7.0.1 
    @sveltejs/kit: ^2.63.0 => 2.69.2 
    @sveltejs/vite-plugin-svelte: ^7.1.2 => 7.2.0 
    svelte: ^5.56.1 => 5.56.4 
    vite: ^8.0.16 => 8.1.4

Severity

annoyance

Additional Information

While the example here is fabricated for demonstration purposes, there are genuine circumstances where this syntax makes sense to use, for example if a helper is used to generate similar load and actions functions for a set of related pages:

import { myhelper } from '@/myhelperlibrary.js';
export const { load, actions } = myhelper(...);

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions