Skip to content

Commit e86dada

Browse files
authored
fix(types): fix types when using legacy components in Svelte 5 (#424)
1 parent 5aa405a commit e86dada

File tree

3 files changed

+43
-8
lines changed

3 files changed

+43
-8
lines changed

src/__tests__/fixtures/Typed.svelte

+5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
<script lang="ts">
2+
import { createEventDispatcher } from 'svelte'
3+
24
export let name: string
35
export let count: number
46
57
export const hello: string = 'hello'
8+
9+
const dispatch = createEventDispatcher<{ greeting: string }>()
610
</script>
711

812
<h1>hello {name}</h1>
913
<p>count: {count}</p>
14+
<button on:click={() => dispatch('greeting', 'hello')}>greet</button>

src/__tests__/render-runes.test-d.ts

+31-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { expectTypeOf } from 'expect-type'
2-
import { describe, test } from 'vitest'
2+
import { describe, test, vi } from 'vitest'
33

44
import * as subject from '../index.js'
5+
import LegacyComponent from './fixtures/Typed.svelte'
56
import Component from './fixtures/TypedRunes.svelte'
67

78
describe('types', () => {
@@ -37,3 +38,32 @@ describe('types', () => {
3738
}>()
3839
})
3940
})
41+
42+
describe('legacy component types', () => {
43+
test('render accepts events', () => {
44+
const onGreeting = vi.fn()
45+
subject.render(LegacyComponent, {
46+
props: { name: 'Alice', count: 42 },
47+
events: { greeting: onGreeting },
48+
})
49+
})
50+
51+
test('component $set and $on are not allowed', () => {
52+
const onGreeting = vi.fn()
53+
const { component } = subject.render(LegacyComponent, {
54+
name: 'Alice',
55+
count: 42,
56+
})
57+
58+
expectTypeOf(component).toMatchTypeOf<{ hello: string }>()
59+
60+
// @ts-expect-error: Svelte 5 mount does not return `$set`
61+
component.$on('greeting', onGreeting)
62+
63+
// @ts-expect-error: Svelte 5 mount does not return `$set`
64+
component.$set({ name: 'Bob' })
65+
66+
// @ts-expect-error: Svelte 5 mount does not return `$destroy`
67+
component.$destroy()
68+
})
69+
})

src/component-types.d.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,17 @@ export type Props<C extends Component> = ComponentProps<C>
4545
* In Svelte 5, this is the set of variables marked as `export`'d.
4646
* In Svelte 4, this is simply the instance of the component class.
4747
*/
48-
export type Exports<C> = C extends LegacyComponent
49-
? C
50-
: C extends ModernComponent<any, infer E>
48+
export type Exports<C> = IS_MODERN_SVELTE extends true
49+
? C extends ModernComponent<any, infer E>
5150
? E
52-
: never
51+
: C & { $set: never; $on: never; $destroy: never }
52+
: C
5353

5454
/**
5555
* Options that may be passed to `mount` when rendering the component.
5656
*
5757
* In Svelte 4, these are the options passed to the component constructor.
5858
*/
59-
export type MountOptions<C extends Component> = C extends LegacyComponent
60-
? LegacyConstructorOptions<Props<C>>
61-
: Parameters<typeof mount<Props<C>, Exports<C>>>[1]
59+
export type MountOptions<C extends Component> = IS_MODERN_SVELTE extends true
60+
? Parameters<typeof mount<Props<C>, Exports<C>>>[1]
61+
: LegacyConstructorOptions<Props<C>>

0 commit comments

Comments
 (0)