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

Svelte 5: ComponentType is still a constructor #11472

Closed
r-thomson opened this issue May 5, 2024 · 9 comments · Fixed by #11775
Closed

Svelte 5: ComponentType is still a constructor #11472

r-thomson opened this issue May 5, 2024 · 9 comments · Fixed by #11775
Assignees
Milestone

Comments

@r-thomson
Copy link

Describe the bug

In Svelte 5, components are no longer classes. However, the ComponentType type is still defined as a class constructor, not a function. This leads to situations where perfectly correct code is flagged as incorrect by the type checker.

Reproduction

Here is a simple example of trying to “wrap” a component:

import MyComponent from "./MyComponent.svelte";
const WrappedComponent = (anchor, props) => MyComponent(anchor, { ...props });

This code generates the TypeScript error Value of type 'typeof MyComponent__SvelteComponent_' is not callable. Did you mean to include 'new'?.

Logs

No response

System Info

System:
    OS: macOS 14.4.1
    CPU: (10) arm64 Apple M1 Pro
    Memory: 111.14 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.0.0 - /opt/homebrew/bin/node
    Yarn: 1.22.22 - /opt/homebrew/bin/yarn
    npm: 10.5.1 - /opt/homebrew/bin/npm
  Browsers:
    Safari: 17.4.1
  npmPackages:
    svelte: ^5.0.0-next.123 => 5.0.0-next.123

Severity

annoyance

@dummdidumm
Copy link
Member

The real shape of components is deliberately hidden. Doing something like this is prone to break because it's relying on private API.
What is the use case for wrapping the component? Wondering if a dedicated API should be introduced for that instead.

@dummdidumm dummdidumm added this to the 5.0 milestone May 5, 2024
@paoloricciuti
Copy link
Member

Wondering if a dedicated API should be introduced for that instead.

That would be cool for "higher order components". For example I created a dialog component that uses a bit of Inline JS to be available before the bundle loads (for progressive enhancement). However this requires having the same Id of the trigger. Currently you have to remember to pass the same id. With such API I could create a create dialog function that return the trigger and the dialog while also specifying the id prop by himself.

@r-thomson
Copy link
Author

The real shape of components is deliberately hidden. Doing something like this is prone to break because it's relying on private API.

Maybe this is the case starting in Svelte 5, but in Svelte 4 this API seems to be reasonably well documented.

What is the use case for wrapping the component? Wondering if a dedicated API should be introduced for that instead.

Here’s my actual use case: Svelte 4, Svelte 5 (gross hack version)

dummdidumm added a commit that referenced this issue May 10, 2024
#11472 brought up a gap we have with the new API currently: There's no way to decorate a component right now. With the old class syntax this was straightforward because you would extend the class and for example modify the props on the way in. This adds `decorateComponent` to achieve the same.
@dummdidumm dummdidumm self-assigned this May 16, 2024
@VismaTobbe
Copy link

VismaTobbe commented May 27, 2024

The real shape of components is deliberately hidden. Doing something like this is prone to break because it's relying on private API. What is the use case for wrapping the component? Wondering if a dedicated API should be introduced for that instead.

Have one question about Svelte 5 and removal of constructor for the component. Today i export some of my components as isolated es modules that "anyone" can lazy load with import(...) and then call the constructor to initialize the component. Will this be breaking now 😰?

@dummdidumm
Copy link
Member

Yes it would break when calling new Component(..), instead people should do mount(Component, ..) now: https://svelte-5-preview.vercel.app/docs/breaking-changes#components-are-no-longer-classes

@VismaTobbe
Copy link

VismaTobbe commented May 27, 2024

Yes it would break when calling new Component(..), instead people should do mount(Component, ..) now: https://svelte-5-preview.vercel.app/docs/breaking-changes#components-are-no-longer-classes

That would mean they need to install Svelte or I now need to wrap the mount myself, right? Oboy...

@dummdidumm
Copy link
Member

If it's meant to be consumed standalone, then yes you need to wrap it yourself.

@Neptunium1129
Copy link

Yes it would break when calling new Component(..), instead people should do mount(Component, ..) now: https://svelte-5-preview.vercel.app/docs/breaking-changes#components-are-no-longer-classes

That would mean they need to install Svelte or I now need to wrap the mount myself, right? Oboy...

i have question about `new Component and mount
example svelte simple modal
-> https://github.com/flekschas/svelte-simple-modal

<!-- App.svelte -->
<script>
  import Content from './Content.svelte';
  import Modal from 'svelte-simple-modal';
</script>

<Modal><Content /></Modal>


<!-- Content.svelte -->
<script>
  import { getContext } from 'svelte';
  import Popup from './Popup.svelte';
  const { open } = getContext('simple-modal');
  **const showSurprise = () => open(Popup, { message: "It's a modal!" });**


</script>

<p><button on:click={showSurprise}>Show me a surprise!</button></p>


<!-- Popup.svelte -->
<script>
  export let message = 'Hi';
</script>

<p>🎉 {message} 🍾</p>

open(Popup, { message: "It's a modal!" });
components-are-no-longer-classes -> Popup
how to change this situation?

image

I wonder if my method is right.

@dummdidumm
Copy link
Member

see my answer at flekschas/svelte-simple-modal#113 (comment)

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

Successfully merging a pull request may close this issue.

5 participants