···11+## Usage
22+33+```bash
44+$ npm install # or pnpm install or yarn install
55+```
66+77+### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs)
88+99+## Available Scripts
1010+1111+In the project directory, you can run:
1212+1313+### `npm run dev`
1414+1515+Runs the app in the development mode.<br>
1616+Open [http://localhost:5173](http://localhost:5173) to view it in the browser.
1717+1818+### `npm run build`
1919+2020+Builds the app for production to the `dist` folder.<br>
2121+It correctly bundles Solid in production mode and optimizes the build for the best performance.
2222+2323+The build is minified and the filenames include the hashes.<br>
2424+Your app is ready to be deployed!
2525+2626+## Deployment
2727+2828+Learn more about deploying your application with the [documentations](https://vite.dev/guide/static-deploy.html)
···11+import { onCleanup } from 'solid-js';
22+33+type UnknownFunction = (...args: any[]) => any;
44+55+type InferEventType<TTarget> = TTarget extends {
66+ // we infer from 2 overloads which are super common for event targets in the DOM lib
77+ // we "prioritize" the first one as the first one is always more specific
88+ addEventListener(type: infer P, ...args: any): void;
99+ // we can ignore the second one as it's usually just a fallback that allows bare `string` here
1010+ // we use `infer P2` over `any` as we really don't care about this type value
1111+ // and we don't want to accidentally fail a type assignability check, remember that `any` isn't assignable to `never`
1212+ addEventListener(type: infer _P2, ...args: any): void;
1313+}
1414+ ? P & string
1515+ : never;
1616+1717+type InferEvent<TTarget, TType extends string> = `on${TType}` extends keyof TTarget
1818+ ? Parameters<Extract<TTarget[`on${TType}`], UnknownFunction>>[0]
1919+ : Event;
2020+2121+// For listener objects, the handleEvent function has the object as the `this` binding
2222+type ListenerObject<TEvent extends Event> = {
2323+ handleEvent(this: ListenerObject<TEvent>, event: TEvent): void;
2424+};
2525+2626+// event listeners can be an object or a function
2727+export type Listener<TTarget extends EventTarget, TType extends string> =
2828+ | ListenerObject<InferEvent<TTarget, TType>>
2929+ | { (this: TTarget, ev: InferEvent<TTarget, TType>): void };
3030+3131+export const createEventListener = <
3232+ TTarget extends EventTarget,
3333+ TType extends InferEventType<TTarget> | (string & {}),
3434+>(
3535+ target: TTarget,
3636+ type: TType,
3737+ listener: Listener<TTarget, TType>,
3838+ options?: boolean | AddEventListenerOptions,
3939+) => {
4040+ onCleanup(target.removeEventListener.bind(target, type, listener, options));
4141+ target.addEventListener(type, listener, options);
4242+};