Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TS doesn't understand mount() return type #14966

Closed
Bilge opened this issue Jan 9, 2025 · 11 comments
Closed

TS doesn't understand mount() return type #14966

Bilge opened this issue Jan 9, 2025 · 11 comments

Comments

@Bilge
Copy link

Bilge commented Jan 9, 2025

Describe the bug

If I assign the result of mount(Foo) to a variable typed Foo, TS gets confused and emits:

TS2322: Type '{ $on?(type: string, callback: (e: any) => void): () => void; $set?(props: Partial<Record<string, any>>): void; } & Record<string, any>' is not assignable to type 'Comp | undefined'.

Nevertheless, svelte-check finds no errors and my editor understands the return type of mount(Foo) is Foo. It is only TS compilation via webpack that is problematic.

Reproduction

new class {
    private foo?: Foo;

    constructor() {
        this.foo = mount(Foo, {target: document.body}); // TS2322
    }
}

Logs

Here are my tsconfig.json files.

{
  "extends": "..",
  "compilerOptions": {
    "verbatimModuleSyntax": true,
  },
}

(This is ..)

{
  "extends": "@tsconfig/recommended/tsconfig.json",
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2020",
    "moduleResolution": "node",
    "moduleSuffixes": ["", ".svelte"],
    "allowJs": true,
  }
}

Relevant portion of webpack.config.js.

module.exports = (env, options) => {
    return {
        module: {
            rules: [
                {
                    test: /\.tsx?$/,
                    loader: 'ts-loader',
                    options: {
                        compilerOptions: {
                            sourceMap: !prod,
                        },
                    },
                    resolve: {
                        extensions: ['.ts', '.svelte.ts', '.js'],
                    },
                },
                {
                    test: /\.svelte$/,
                    loader: 'svelte-loader',
                    options: {
                        emitCss: true,
                        preprocess: sveltePreprocess({
                            sourceMap: !prod,
                        }),
                        compilerOptions: {
                            dev: !prod,
                        },
                    },
                    resolve: {
                        extensions: ['.ts'],
                    },
                },
            ],
        },
    };
}; 

System Info

System:
    OS: Linux 5.15 Ubuntu 20.04.3 LTS (Focal Fossa)
    CPU: (8) x64 Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz
    Memory: 8.36 GB / 11.69 GB
    Container: Yes
    Shell: 5.0.17 - /bin/bash
  Binaries:
    Node: 22.12.0 - /run/user/1000/fnm_multishells/1717_1736443941005/bin/node
    Yarn: 1.22.22 - /run/user/1000/fnm_multishells/1717_1736443941005/bin/yarn
    npm: 10.9.0 - /run/user/1000/fnm_multishells/1717_1736443941005/bin/npm
  npmPackages:
    svelte: ^5.0.0 => 5.16.1
    webpack: ^5.11.0 => 5.97.1

Severity

blocking all usage of svelte

@7nik
Copy link
Contributor

7nik commented Jan 9, 2025

The TS's type ({ $on?(...): () => void; $set?(...): void; } & Record<string, any>) is the correct one.
The component constructor (Foo) and component instance (returned by mount) are entirely different things.

@webJose
Copy link
Contributor

webJose commented Jan 9, 2025

@Bilge so as to try to clear things up: Svelte v5 components are no longer classes and instead they are functions. So your private foo not be storing an instance of Foo since it is no longer a class. Furthermore, what mount() returns is an object with the component's exports. If the component exports nothing, then you'll get an empty object.

@Bilge
Copy link
Author

Bilge commented Jan 9, 2025

OK? But I need some way to type my local variable such that I know what it exports and what methods I can call on it.

@webJose
Copy link
Contributor

webJose commented Jan 10, 2025

Don't type it explicitly. TypeScript will infer the type from the construction assignment.

@Bilge
Copy link
Author

Bilge commented Jan 10, 2025

lol, no.

TS7008: Member foo implicitly has an any type.

@webJose
Copy link
Contributor

webJose commented Jan 10, 2025

Works fine for me:

image

@Bilge
Copy link
Author

Bilge commented Jan 10, 2025

Yeah, that's because you don't have strict mode on. It's part of @tsconfig/recommended.

@webJose
Copy link
Contributor

webJose commented Jan 10, 2025

Eh, apparently not the case. I checked the configuration, and by default, strict mode seems to be set:

image

I also explicitly added strict: true to tsconfig.json and restarted VS Code's TypeScript server and it still worked.

@7nik
Copy link
Contributor

7nik commented Jan 10, 2025

In Svelte 5, the instance type is ReturnType<Foo>.

my editor understands the return type of mount(Foo) is Foo

You also need to fix this

@dummdidumm
Copy link
Member

You need to disable webpack's type checking, it does not know about the exact value of Svelte component exports: https://stackoverflow.com/questions/60278796/how-to-ignore-typescript-errors-when-compile-by-webpack-production-mode

@dummdidumm dummdidumm closed this as not planned Won't fix, can't repro, duplicate, stale Jan 10, 2025
@Jojoshua
Copy link

You need to disable webpack's type checking, it does not know about the exact value of Svelte component exports: https://stackoverflow.com/questions/60278796/how-to-ignore-typescript-errors-when-compile-by-webpack-production-mode

I'm now looking at migrating to svelte 5 and I'm experiencing this same issue. Although I also use webpack + fork-ts-checker-webpack-plugin so TS errors are reported back I also see the same errors are reported just doing npx tsc --noEmit which I would think takes webpack out of the equation right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants