Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/long-humans-dress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: ensure createEventDispatcher works with types from generics
2 changes: 1 addition & 1 deletion documentation/docs/05-misc/03-typescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ Events can be typed with `createEventDispatcher`:
import { createEventDispatcher } from 'svelte';

const dispatch = createEventDispatcher<{
event: never; // does not accept a payload
event: null; // does not accept a payload
type: string; // has a required string payload
click: string | null; // has an optional string payload
}>();
Expand Down
2 changes: 1 addition & 1 deletion documentation/docs/05-misc/04-v4-migration-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher<{
optional: number | null;
required: string;
noArgument: never;
noArgument: null;
}>();

// Svelte version 3:
Expand Down
10 changes: 4 additions & 6 deletions packages/svelte/src/runtime/internal/public.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,12 @@ export interface DispatchOptions {
export interface EventDispatcher<EventMap extends Record<string, any>> {
// Implementation notes:
// - undefined extends X instead of X extends undefined makes this work better with both strict and nonstrict mode
// - [X] extends [never] is needed, X extends never would reduce the whole resulting type to never and not to one of the condition outcomes
// - | null | undefined is added for convenience, as they are equivalent for the custom event constructor (both result in a null detail)
<Type extends keyof EventMap>(
...args: [EventMap[Type]] extends [never]
? [type: Type, parameter?: null | undefined, options?: DispatchOptions]
: null extends EventMap[Type]
? [type: Type, parameter?: EventMap[Type], options?: DispatchOptions]
...args: null extends EventMap[Type]
? [type: Type, parameter?: EventMap[Type] | null | undefined, options?: DispatchOptions]
: undefined extends EventMap[Type]
? [type: Type, parameter?: EventMap[Type], options?: DispatchOptions]
? [type: Type, parameter?: EventMap[Type] | null | undefined, options?: DispatchOptions]
: [type: Type, parameter: EventMap[Type], options?: DispatchOptions]
): boolean;
}
2 changes: 1 addition & 1 deletion packages/svelte/test/types/actions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Action, ActionReturn } from '$runtime/action';
import type { Action, ActionReturn } from '$runtime/action/public';

// ---------------- Action

Expand Down
2 changes: 1 addition & 1 deletion packages/svelte/test/types/create-event-dispatcher.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createEventDispatcher } from '$runtime/internal/lifecycle';

const dispatch = createEventDispatcher<{
loaded: never;
loaded: null;
change: string;
valid: boolean;
optional: number | null;
Expand Down