-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Typed event dispatcher and event handlers #5211
Comments
I propose a different typing which would only change the typing but keep the implementation the same: export declare function createEventDispatcher<EventMap extends {} = any>()
: <EventKey extends Extract<keyof EventMap, string>>(type: EventKey, detail?: EventMap[EventKey]) => void;
const bla = createEventDispatcher();
bla('anythingAllowedSinceNoEventMapTypingGiven', true);
const bla2 = createEventDispatcher<{click: boolean}>();
bla2('qwd', true); // <-- error, "qwd" not assignable to type "click"
bla2('click', ''); // <-- error, string not assignable to type boolean |
Makes it possible to explicitly type which events can be dispatched like so: ```ts const bla2 = createEventDispatcher<{click: boolean}>(); bla2('click', ''); // error, type string not assignable to type boolean bla2('qwd', true); // error, "qwd" not assignable to "click" ``` sveltejs#5211
But does this ensure in other components that when I listen to |
This is an issue for the |
Closing since the intent of this issue was to get type-safe event-handling. Dispatching in a type safe way within the component was added with the enhanced typings. Getting IDE support for typed event dispatchers on other components will be work to do in the language-tools. |
Svelte 3.25.0 now has |
Could you reopen this? This is not what I described in this issue. The issue's title states "Typed event dispatcher and event handlers", not just event dispatchers These new typings only restrict the events that have to be dispatched. Take a look at what I described in the Although I like the idea that you can define the types of the events per event in one type, I think my suggestion is needed for of the second part and thats why this issue is opened in this repository. The reason being that even if I were to bring the type of the event handler myself to the recieving end I can't extract correct types from this. Unless I define it explicitly, but inference is preferred. const eh = createEventDispatcher<{ hello: { world: number }, foo: {bar: string} }>();
eh('hello', { world: 12 });
eh('foo', { bar: '12' });
function handle(a: Parameters<typeof eh>[1]) {
//a: {
// world: number;
//} | {
// bar: string;
//} | undefined
} Even if I could define multiple event dispatchers (Technically I think I can) that defeats the purpose of being able to define the types of multiple events at once. |
I stated above that this is something that needs to be handled in language tools. We will add support for it soon. That work can be tracked here sveltejs/language-tools#424 . |
I think it can work out with this kind of event dispatcher generics if it's possible in typescript to union the generics of all event dispatchers defined (In the case of svelte) |
Here are some more details for people searching how to use the new createEventDispatcher:
|
@doom-goober I just asked a question about it at so What is the correct way to type an event with no detail? |
@opensas I also answered on SO but I gave a poor answer there. The TL;DR is that I would do eventName:null OR eventName:{}. That's because both null and {} (empty object} are both of type object. I know in my example I did eventName:void (I don't remember where I got that example from.) But in the end, remember that the generic only matters at compile time to TypeScript and the generic will be stripped out by the compiled JavaScript, so as long as it compiles and gives the right warnings, it doesn't really matter. But the rational choice would be null or {} (empty object) because they have type consistency. |
@doom-goober thanks a lot for your reply. I'll just go with
|
I have created a PR that improves the type-definitions of @opensas thanks for the link to the MDN docs. I first assued the default value was |
I hope it gets merged, and also that we can find it in the docs. Svelte documentation is great, but sometimes is not so easy to find how to type components and events. |
I also had this Problem a few times. I'm currently working on a repo where all the TypeScript features of Svelte and SvelteKit are shown. |
Is your feature request related to a problem? Please describe.
I'd like to have typesafe event handlers, for this the type of the event has to be known beforehand.
Describe the solution you'd like
The
createEventDispatcher
function being extended with a generic and a parameter. The parameter would restrict the handler to only handle one kind of event, where thedetail
field's type would be determined by the type of the generic.The new type signature of
createEventDispatcher
would look like this:Example usage
child.svelte
app.svelte
Possible problems
The svelte compiler has to be sure that only one
createEventDispatcher
have been defined for any giventype
, to prevent redefing the dispatcher with a different type. (This is easier if eventDispatchers are only allowed to be created on the top level and asconst
, but this would be a breaking change)TypeScript can't protect against something like dispatching a malformed event through a regular
eventDispatcher
. To solve this either the untypedcreateEventDispatcher()
would need to be deprecated, or the svelte compiler has to forbid the mixed usage of these.How important is this feature to you?
It's important to provide type safety where it's possible.
The text was updated successfully, but these errors were encountered: