diff --git a/.changeset/wet-games-fly.md b/.changeset/wet-games-fly.md new file mode 100644 index 0000000000..9f03e26882 --- /dev/null +++ b/.changeset/wet-games-fly.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: type-level back-compat for default slot and children prop diff --git a/packages/svelte/src/main/public.d.ts b/packages/svelte/src/main/public.d.ts index 63f5122bbe..5849835ea2 100644 --- a/packages/svelte/src/main/public.d.ts +++ b/packages/svelte/src/main/public.d.ts @@ -18,6 +18,14 @@ export interface ComponentConstructorOptions< $$inline?: boolean; } +// Utility type for ensuring backwards compatibility on a type level: If there's a default slot, add 'children' to the props if it doesn't exist there already +type PropsWithChildren = Props & + (Props extends { children?: any } + ? {} + : Slots extends { default: any } + ? { children?: Snippet } + : {}); + /** * Can be used to create strongly typed Svelte components. * @@ -57,13 +65,13 @@ export class SvelteComponent< * is a stop-gap solution. Migrate towards using `mount` or `createRoot` instead. See * https://svelte-5-preview.vercel.app/docs/breaking-changes#components-are-no-longer-classes for more info. */ - constructor(options: ComponentConstructorOptions); + constructor(options: ComponentConstructorOptions>); /** * For type checking capabilities only. * Does not exist at runtime. * ### DO NOT USE! * */ - $$prop_def: Props; + $$prop_def: PropsWithChildren; /** * For type checking capabilities only. * Does not exist at runtime. diff --git a/packages/svelte/tests/types/component.ts b/packages/svelte/tests/types/component.ts index 749c648e2f..13ebb65753 100644 --- a/packages/svelte/tests/types/component.ts +++ b/packages/svelte/tests/types/component.ts @@ -15,11 +15,11 @@ class LegacyComponent extends SvelteComponent< { slot: { slotProps: boolean } } > {} -// @ts-expect-error const legacyComponent = new LegacyComponent({ target: null as any as Document | Element | ShadowRoot, props: { prop: 'foo', + // @ts-expect-error x: '' } }); @@ -56,14 +56,20 @@ class NewComponent extends SvelteComponent< anExport: string = ''; } -// @ts-expect-error new NewComponent({ - prop: 'foo', - x: '' + target: null as any, + props: { + prop: 'foo', + // @ts-expect-error + x: '' + } }); const newComponent: NewComponent = new NewComponent({ - prop: 'foo' + target: null as any, + props: { + prop: 'foo' + } }); newComponent.$$events_def.event; // @ts-expect-error @@ -123,11 +129,11 @@ instance.anExport === 1; // --------------------------------------------------------------------------- interop const AsLegacyComponent = asClassComponent(newComponent); -// @ts-expect-error new AsLegacyComponent({ target: null as any, props: { prop: '', + // @ts-expect-error x: '' } });