Reputation: 61
I try to implement a functional way to define WebComponent and I struggle with events. Here is what I did for the moment:
class BaseCustomComponent<Events> extends HTMLElement {
whenEvent<K extends keyof Events>(eventName: K, callback: (event: CustomEvent<Events[K]>) => void) {
// Do something to listen to the event
}
}
const defineComponent = <Events>(
setup: (context: {
useEvents: <U>() => <K extends keyof U>(eventName: K, detail: U[K]) => void,
}) => {
onConnect?: () => void;
}
) => {
class CustomComponent extends BaseCustomComponent<Events> {
private readonly onConnect?: () => void;
constructor() {
super();
const useEvents = <U>() => {
return <K extends keyof U>(eventName: K, detail: U[K]) => {
// Do something to fire the event
};
};
const { onConnect } = setup({ useEvents });
this.onConnect = onConnect;
}
connectedCallback() {
this.onConnect?.();
}
}
// Do something to register the component
return CustomComponent;
}
I would like to be able to "infer" the type defined inside the component:
const componentA = defineComponent(({ useEvents }) => {
const emit = useEvents<{
clicked: number;
}>();
const onConnect = () => {
emit('clicked', 1);
emit('clicked', '2'); // Working well: Error because the event type is number
};
return { onConnect };
});
const domElement = document.createElement('my-component') as InstanceType<typeof componentA>
domElement.whenEvent('clicked', ({ detail }) => console.log(detail)); // EventName is of type never
I would like to be able to infer in some way the type defined in the function defining the component so that domElement.whenEvent('clicked', /* waiting for number callback */)
I am open to any suggestions about refactoring, I would just avoid to have to specify the generic like that:
const componentA = defineComponent<{ clicked: number; }>(({ useEvents }) => {
...
});
Upvotes: 0
Views: 24