Skip to content

Commit 4f1f8d8

Browse files
committed
fix: relax Component type
The current type narrows the binding type to `""` by default, which means "no bindings on this component". While this is the common case, it makes it very cumbersome to use the `Component` type because legacy components are of type `string` and as soon as you have bindings, the type is something like `"foo" | "bar"` which _also_ is not assignable to `""` which is semantically wrong, because you should be able to assign a component that can have bindings to a type that accepts none. The pragmatic solution is to change the binding type to allow `string`, which means someone theoretically could use bindings with a component that doesn't have bindings: ```svelte <script> let component: Component<{ prop: boolean }> = IAcceptNoBindings; </script> <!-- allowed but should be a type error --> <svelte:component this={component} bind:prop={foo} /> ``` But this is a) rare anyway and b) can be caught at runtime This came up in comments of #11775
1 parent 9f823b9 commit 4f1f8d8

File tree

4 files changed

+11
-4
lines changed

4 files changed

+11
-4
lines changed

.changeset/chilly-laws-juggle.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"svelte": patch
3+
---
4+
5+
fix: relax `Component` type

packages/svelte/src/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ export class SvelteComponent<
129129
export interface Component<
130130
Props extends Record<string, any> = {},
131131
Exports extends Record<string, any> = {},
132-
Bindings extends keyof Props | '' = ''
132+
Bindings extends keyof Props | '' = string
133133
> {
134134
/**
135135
* @param internal An internal object used by Svelte. Do not use or modify.

packages/svelte/tests/types/component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,8 @@ const functionComponent: Component<
204204
};
205205
functionComponent.element === HTMLElement;
206206

207+
const bindingIsOkayToWiden: Component<any> = functionComponent;
208+
207209
functionComponent(null as any, {
208210
binding: true,
209211
// @ts-expect-error

packages/svelte/types/index.d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ declare module 'svelte' {
126126
export interface Component<
127127
Props extends Record<string, any> = {},
128128
Exports extends Record<string, any> = {},
129-
Bindings extends keyof Props | '' = ''
129+
Bindings extends keyof Props | '' = string
130130
> {
131131
/**
132132
* @param internal An internal object used by Svelte. Do not use or modify.
@@ -1990,7 +1990,7 @@ declare module 'svelte/legacy' {
19901990
*
19911991
* */
19921992
export function createClassComponent<Props extends Record<string, any>, Exports extends Record<string, any>, Events extends Record<string, any>, Slots extends Record<string, any>>(options: import("svelte").ComponentConstructorOptions<Props> & {
1993-
component: import("svelte").ComponentType<import("svelte").SvelteComponent<Props, Events, Slots>> | import("svelte").Component<Props, any, "">;
1993+
component: import("svelte").ComponentType<import("svelte").SvelteComponent<Props, Events, Slots>> | import("svelte").Component<Props, any, string>;
19941994
immutable?: boolean | undefined;
19951995
hydrate?: boolean | undefined;
19961996
recover?: boolean | undefined;
@@ -2001,7 +2001,7 @@ declare module 'svelte/legacy' {
20012001
* @deprecated Use this only as a temporary solution to migrate your imperative component code to Svelte 5.
20022002
*
20032003
* */
2004-
export function asClassComponent<Props extends Record<string, any>, Exports extends Record<string, any>, Events extends Record<string, any>, Slots extends Record<string, any>>(component: import("svelte").SvelteComponent<Props, Events, Slots> | import("svelte").Component<Props, any, "">): import("svelte").ComponentType<import("svelte").SvelteComponent<Props, Events, Slots> & Exports>;
2004+
export function asClassComponent<Props extends Record<string, any>, Exports extends Record<string, any>, Events extends Record<string, any>, Slots extends Record<string, any>>(component: import("svelte").SvelteComponent<Props, Events, Slots> | import("svelte").Component<Props, any, string>): import("svelte").ComponentType<import("svelte").SvelteComponent<Props, Events, Slots> & Exports>;
20052005
/**
20062006
* Runs the given function once immediately on the server, and works like `$effect.pre` on the client.
20072007
*

0 commit comments

Comments
 (0)