Language-tools: Discusión: ¿Cómo podemos escribir los eventos apoyados por un componente?

Creado en 5 ago. 2020  ·  5Comentarios  ·  Fuente: sveltejs/language-tools

El objetivo es detectar fácilmente errores tipográficos y ayudar a descubrir todos los posibles eventos enviados por un componente. Después de todo, no hay ninguna razón por la que las entradas (accesorios) puedan tener un contrato fuerte, pero las salidas (eventos) no. De hecho, es incluso más importante que para los accesorios, porque el envío puede ocurrir en cualquier parte del archivo, mientras que los accesorios generalmente están agrupados cuidadosamente en la parte superior.

Ahora mismo puedo escribir on:qoidfoqidjoiqsjd muy bien.

Flex, que también tenía su compilador usaba anotaciones personalizadas para esto: https://github.com/apache/flex-sdk/blob/master/frameworks/projects/mx/src/mx/core/Container.as#L97

Quizás podríamos tener una convención especial reservada como export type Events = {name: 'eventA', data: number} | ...
Tener el TSDoc en la información sobre herramientas del lado del consumidor sería la guinda del pastel.

enhancement

Comentario más útil

Ahora puede aprovechar la escritura createEventDispatcher introducida en Svelte 3.25.0. Si lo haces

const dispatch = createEventDispatcher<{foo: string; bar: boolean}>();

Obtiene una escritura fuerte para dispatch dentro del componente, y si escucha los eventos foo / bar , obtendrá una escritura sólida:

on:foo={e => ... // <- e is of type CustomEvent<string>

También obtendrá una función de autocompletado mucho mejor para los eventos ahora. Sin embargo, tenga en cuenta que todavía puede escuchar otros eventos, por lo que escribir seguridad en el sentido de que "solo escuchar eventos definidos a través de createEventDispatcher " solo es posible a través de la interfaz ComponentEvents . Pero planeamos proporcionar algo (tal vez un atributo de etiqueta de script) que haría que los eventos fueran estrictos.

Documentos relacionados: https://github.com/sveltejs/language-tools/blob/master/docs/preprocessors/typescript.md#typing -component-events

Todos 5 comentarios

La razón por la que esto no se puede implementar fácilmente es que es mucho más difícil recopilar todos los eventos posibles que recopilar los accesorios. Esa también es la razón por la que el autocompletado no funciona porque son para accesorios.

Mirando bajo el capó, es que los accesorios se implementan a través de accesorios jsx. Los eventos no se deben a las limitaciones de recopilarlos. Si el usuario los escribe explícitamente, esto podría cambiarse. No podemos marcar los eventos enviados como "esto no se ajusta a la definición" debido a los desafíos mencionados.

Tener una interfaz reservada es probablemente el camino a seguir. Hemos pensado en esto antes en el contexto de los accesorios genéricos. Los nombres de interfaz reservados podrían ser ComponentEvents , ComponentProps , ComponentSlots y ComponentDef para escribir los tres.

Relacionado # 304

Obtener el autocompletado con on:<event> tiene que hacerse de manera diferente porque, bajo el capó, usamos JSX para obtener estos autocompletados. Para obtener el autocompletado "listo para usar", necesitaríamos tener on:<event> como parte de los accesorios. Pero esto no es posible porque JSX no permite caracteres como : en accesorios.
Otro problema es que de alguna manera necesitaríamos convertir la definición de tipo de eventos para anteponer on: , lo que no se puede hacer con TypeScript en este momento ( problema relacionado con TS ).

De estas limitaciones surgen dos soluciones:

  • Dígales a los desarrolladores que escriban sus eventos como __on__<eventName>: .. y lo haríamos en el servidor de idioma y luego reemplazaríamos __on__ con on: durante el autocompletado. Esto se siente subóptimo y quebradizo.
  • Implemente nuestro "propio" autocompletado para esto. Esta es posiblemente una tarea difícil, pero conduciría a una solución limpia.

Obtener errores " on:XXX no existe" es fácilmente posible después de que # 386 se fusiona a través de una variación de la definición del método $on que no retrocede a CustomEvent<any> si los usuarios escriben sus eventos explícitamente .

Una vez que se publica https://github.com/sveltejs/svelte/pull/5260 , podemos intentar actualizar svelte2tsx para que busque createEventDispatcher , busque si tiene una anotación de tipo y si es así, usa eso para obtener los tipos adecuados.

Ahora puede aprovechar la escritura createEventDispatcher introducida en Svelte 3.25.0. Si lo haces

const dispatch = createEventDispatcher<{foo: string; bar: boolean}>();

Obtiene una escritura fuerte para dispatch dentro del componente, y si escucha los eventos foo / bar , obtendrá una escritura sólida:

on:foo={e => ... // <- e is of type CustomEvent<string>

También obtendrá una función de autocompletado mucho mejor para los eventos ahora. Sin embargo, tenga en cuenta que todavía puede escuchar otros eventos, por lo que escribir seguridad en el sentido de que "solo escuchar eventos definidos a través de createEventDispatcher " solo es posible a través de la interfaz ComponentEvents . Pero planeamos proporcionar algo (tal vez un atributo de etiqueta de script) que haría que los eventos fueran estrictos.

Documentos relacionados: https://github.com/sveltejs/language-tools/blob/master/docs/preprocessors/typescript.md#typing -component-events

@dummdidumm

¿Alguna idea sobre por qué algunos eventos de escucha por createEventDispatcher no reciben el tipo?

Ejemplo:

// Component Foo
const dispatchFoo = createEventDispatcher<{foo: string; bar: boolean}>();
const dispatchBar = createEventDispatcher<{bar: string; baz: string}>();

// Component Bar
// e is CustomEvent<any>
on:foo="{(e) => handleFoo(e.detail.bar)}"
// e is CustomEvent<{baz: string}>
on:bar="{(e) => handleBar(e.detail.bar)}"

El compilador de mecanografiado detecta esto como se esperaba.

Cambiar el orden produce resultados diferentes.

si cambia el orden createEventDispatcher , entonces el compilador de mecanografiado no detecta el error.
Parece que solo el último createEventDispatcher produce el tipo para el oyente.

// Component Foo
const dispatchBar = createEventDispatcher<{bar: string; baz: string}>();
const dispatchFoo = createEventDispatcher<{foo: string; bar: boolean}>();

// Component Bar
// e is CustomEvent<{bar: boolean}>
on:foo="{(e) => handleFoo(e.detail.bar)}"
// e is CustomEvent<any>
on:bar="{(e) => handleBar(e.detail.bar)}"

El compilador de mecanografiado no detecta el error ya que el tipo ahora es CustomEvent<any> .

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

Kingwl picture Kingwl  ·  6Comentarios

JoeDailey picture JoeDailey  ·  6Comentarios

JAD3N picture JAD3N  ·  5Comentarios

canadaduane picture canadaduane  ·  5Comentarios

johanbissemattsson picture johanbissemattsson  ·  4Comentarios