Skip to content

Commit a3bc7d5

Browse files
committed
fix: type-level back-compat for default slot and children prop
If someone has an existing SvelteComponent type definition and using the slot generic to type the default slot, automatically add that slot to the prop type as "children"
1 parent cb4b1f0 commit a3bc7d5

File tree

3 files changed

+27
-8
lines changed

3 files changed

+27
-8
lines changed

.changeset/wet-games-fly.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: type-level back-compat for default slot and children prop

packages/svelte/src/main/public.d.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ export interface ComponentConstructorOptions<
1818
$$inline?: boolean;
1919
}
2020

21+
// 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
22+
type PropsWithChildren<Props, Slots> = Props &
23+
(Props extends { children?: any }
24+
? {}
25+
: Slots extends { default: any }
26+
? { children?: Snippet }
27+
: {});
28+
2129
/**
2230
* Can be used to create strongly typed Svelte components.
2331
*
@@ -57,13 +65,13 @@ export class SvelteComponent<
5765
* is a stop-gap solution. Migrate towards using `mount` or `createRoot` instead. See
5866
* https://svelte-5-preview.vercel.app/docs/breaking-changes#components-are-no-longer-classes for more info.
5967
*/
60-
constructor(options: ComponentConstructorOptions<Props>);
68+
constructor(options: ComponentConstructorOptions<PropsWithChildren<Props, Slots>>);
6169
/**
6270
* For type checking capabilities only.
6371
* Does not exist at runtime.
6472
* ### DO NOT USE!
6573
* */
66-
$$prop_def: Props;
74+
$$prop_def: PropsWithChildren<Props, Slots>;
6775
/**
6876
* For type checking capabilities only.
6977
* Does not exist at runtime.

packages/svelte/tests/types/component.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ class LegacyComponent extends SvelteComponent<
1515
{ slot: { slotProps: boolean } }
1616
> {}
1717

18-
// @ts-expect-error
1918
const legacyComponent = new LegacyComponent({
2019
target: null as any as Document | Element | ShadowRoot,
2120
props: {
2221
prop: 'foo',
22+
// @ts-expect-error
2323
x: ''
2424
}
2525
});
@@ -56,14 +56,20 @@ class NewComponent extends SvelteComponent<
5656
anExport: string = '';
5757
}
5858

59-
// @ts-expect-error
6059
new NewComponent({
61-
prop: 'foo',
62-
x: ''
60+
target: null as any,
61+
props: {
62+
prop: 'foo',
63+
// @ts-expect-error
64+
x: ''
65+
}
6366
});
6467

6568
const newComponent: NewComponent = new NewComponent({
66-
prop: 'foo'
69+
target: null as any,
70+
props: {
71+
prop: 'foo'
72+
}
6773
});
6874
newComponent.$$events_def.event;
6975
// @ts-expect-error
@@ -123,11 +129,11 @@ instance.anExport === 1;
123129
// --------------------------------------------------------------------------- interop
124130

125131
const AsLegacyComponent = asClassComponent(newComponent);
126-
// @ts-expect-error
127132
new AsLegacyComponent({
128133
target: null as any,
129134
props: {
130135
prop: '',
136+
// @ts-expect-error
131137
x: ''
132138
}
133139
});

0 commit comments

Comments
 (0)