En esta publicación de blog, presentaré el concepto de interfaces y cómo pueden ser útiles incluso en lenguajes dinámicos. También usaré la biblioteca Implement.js para llevar el concepto a JavaScript y mostrarle cómo obtener alguna utilidad adicional de las interfaces. ¿Qué es una interfaz? Google define una interfaz como "un punto donde dos sistemas, sujetos, organizaciones, etc. se encuentran e interactúan", y esta definición es válida para las interfaces en la programación. En el desarrollo de software, una interfaz es una estructura que impone propiedades específicas en un objeto; en la mayoría de los lenguajes, este objeto es una clase. Aquí hay un ejemplo de una interfaz en Java: En el ejemplo anterior, la interfaz describe una clase que tiene dos métodos sin tipo de retorno, los cuales toman un único argumento entero. Los detalles de la implementación de cada función se dejan en manos de la clase, por eso ambos métodos no tienen cuerpo. Para garantizar que una clase implemente la interfaz , usamos la palabra clave : Car Car implements Interfaces en JavaScript Las interfaces no son una cosa en JavaScript, no realmente de todos modos. JavaScript es un lenguaje dinámico, en el que los tipos se cambian con tanta frecuencia que es posible que el desarrollador ni siquiera se haya dado cuenta, debido a esto, las personas argumentan que no es necesario agregar una interfaz al estándar ECMAScript en el que se basa JavaScript. Sin embargo, JavaScript ha crecido enormemente como lenguaje de back-end en la forma de Node.js, y eso conlleva diferentes requisitos y una multitud diferente que puede tener una opinión diferente. Para agregar a esto, el lenguaje se está convirtiendo rápidamente en herramienta de front-end; ha llegado al punto en que muchos desarrolladores escribirán la gran mayoría de su HTML dentro de archivos .js en forma de JSX. la Entonces, a medida que el lenguaje crece para asumir más roles, es útil asegurarse de que una de nuestras estructuras de datos más cruciales sea lo que esperábamos que fuera. JavaScript puede tener la palabra clave , pero en realidad es solo una función constructora no instanciada y, una vez que se la llama, es simplemente un objeto. Los objetos son omnipresentes, por lo que a veces es beneficioso asegurarse de que coincidan con una forma específica. class Recientemente, en el trabajo, encontré un caso en el que un desarrollador esperaba que una propiedad devuelta como parte de una respuesta API fuera , pero en cambio obtuvo , lo que provocó un error. Un error fácil, y que también podría haberse evitado si tuviéramos una interfaz. true "true" ¡Pero espera hay mas! Las interfaces, con algunas modificaciones menores, podrían usarse para remodelar objetos. Imagine implementar una interfaz "estricta", donde no se permiten propiedades fuera de la interfaz, podríamos eliminar o cambiar el nombre de estas propiedades, o incluso arrojar un error si las encontramos. Así que ahora tenemos una interfaz que nos dirá cuando nos faltan ciertas propiedades, pero también cuando tenemos propiedades inesperadas, o si los tipos de propiedades no son lo que esperábamos. Esto agrega otras posibilidades, por ejemplo, refactorizar una respuesta de una API mientras se agrega esa capa adicional de seguridad además del comportamiento estándar de la interfaz. También podríamos usar interfaces en pruebas unitarias si tenemos que arrojar errores. Implementar.js es una biblioteca que intenta traer interfaces a JavaScript. La idea es simple: defina una interfaz, defina los tipos de sus propiedades y utilícela para garantizar que un objeto sea lo que espera que sea. Implement.js Configuración Primero instale el paquete: npm instalar implementar-js A continuación, cree un archivo .js e importe , y : implement Interface type Nuestra primera interfaz Para crear una interfaz, simplemente llame a y pase una cadena como el nombre de su interfaz; no se recomienda, pero si omite el nombre, se generará una identificación única. Esto devuelve una función que acepta un objeto donde las propiedades son todos objetos de , también se puede pasar un segundo argumento con opciones para mostrar advertencias, generar errores, eliminar o cambiar el nombre de las propiedades, asegurarse de que estén presentes las propiedades de la interfaz o extender una existente. Interface type solo Interface Aquí hay una interfaz que describe un automóvil: Tiene una propiedad de que debe ser de tipo número, una matriz de pasajeros que contiene objetos que deben implementar la interfaz de y contiene una propiedad de , que debe ser una función. Las opciones de y se han establecido en verdadero, lo que significa que se generarán errores cuando falte una propiedad de la interfaz y también cuando se encuentre una propiedad que en la interfaz. seats Passenger beep error strict no esté Implementando nuestra interfaz Ahora queremos implementar nuestra interfaz, en un ejemplo simple, crearemos un objeto usando un objeto literal y veremos si podemos implementar nuestra interfaz. Primero, creamos un objeto , luego intentaremos implementarlo en nuestra interfaz : Ford Car Como vemos en el comentario anterior, esto arroja un error. Miremos hacia atrás en nuestra interfaz de : Car Podemos ver que si bien todas las propiedades están presentes, el modo estricto también es verdadero, lo que significa que la propiedad adicional provoca que se arroje un error. Además, aunque tenemos una propiedad de , no es una matriz. fuelType passengers Para implementar correctamente la interfaz, eliminamos y cambiamos el valor de para que sea una matriz que contenga objetos que implementen la interfaz : fuelType passengers Passenger "¡Pero JavaScript no es un lenguaje orientado a objetos!" Es cierto que, si bien las interfaces generalmente se asocian con lenguajes orientados a objetos y JavaScript es un lenguaje multiparadigma que utiliza la herencia de prototipos, las interfaces aún pueden ser muy útiles. Por ejemplo, al usar , podemos refactorizar fácilmente una respuesta de API mientras nos aseguramos de que no se haya desviado de lo que esperábamos. Aquí hay un ejemplo usado junto con : implement-js redux-thunk Primero, definimos la interfaz de usuario de , que amplía la interfaz , como un objeto con las propiedades y . es verdadero, lo que significa que descartaremos cualquier propiedad que no se describa en la interfaz de usuario de . Dado que nuestra API devuelve propiedades en un formato poco amigable, hemos cambiado el nombre de las propiedades de y a versiones camelcase de ellas mismas. TwitterUser User twitterId twitterUsername trim TwitterUser twitter_username twitter_id A continuación, definimos una acción asíncrona con , la acción desencadena una llamada a la API y usamos nuestra interfaz para descartar las propiedades que no queremos y asegurarnos de que implemente las propiedades que esperamos, con los tipos correctos. Si prefiere mantener puros a los creadores de sus acciones o no usar , es posible que desee verificar la interfaz dentro y devolver el resultado. redux-thunk TwitterUser redux-thunk twitterService.getUser Nota: cuando se amplía una interfaz, las opciones no se heredan Las pruebas unitarias también son un lugar adecuado para usar interfaces: En resumen Hemos visto cómo las interfaces pueden ser útiles en JavaScript: a pesar de que es un lenguaje muy dinámico, verificar la forma de un objeto y que sus propiedades sean un tipo de datos específico nos brinda una capa adicional de seguridad que de otro modo nos estaríamos perdiendo. Al desarrollar el concepto de interfaces y usar , también hemos podido obtener una utilidad adicional además de la seguridad adicional. implement-js Twitter: @josh_jahans