Los 5 mandamientos del desarrollador de TypeScript

imagen


Cada vez m谩s proyectos y equipos est谩n utilizando TypeScript. Sin embargo, solo aplicar TypeScript y exprimirlo al m谩ximo es algo muy diferente.


Le presento una lista de las mejores pr谩cticas de alto nivel para usar TypeScript que lo ayudar谩n a aprovechar al m谩ximo este lenguaje.


No mientas


Tipos es un contrato. 驴Qu茅 significa esto? Cuando implementa una funci贸n, su tipo se convierte en una promesa para otros desarrolladores (隆o para usted mismo en el futuro!) Que, cuando se llama, esta funci贸n devolver谩 un cierto tipo de valor.


En el siguiente ejemplo, el tipo de la funci贸n getUser asegura que devuelve un objeto que siempre tiene dos propiedades: name y age .


 interface User { name: string; age: number; } function getUser(id: number): User { /* ... */ } 

TypeScript es un lenguaje muy flexible. Tiene muchos compromisos dise帽ados para facilitar la introducci贸n del lenguaje. Por ejemplo, le permite implementar la funci贸n getUser esta manera:


 function getUser(id: number): User { return { age: 12 } as User; } 

隆No hagas eso! Esto es falso. Al crear dicho c贸digo, Mientes a otros desarrolladores (que usar谩n tu funci贸n en sus funciones). Esperan que el objeto devuelto por getUser siempre tenga alg煤n tipo de campo de name . 隆Pero 茅l no est谩 all铆! Adem谩s, 驴qu茅 sucede cuando su colega escribe getUser(1).name.toString() ? Sabes muy bien que ...


Aqu铆, por supuesto, la mentira parece obvia. Sin embargo, al trabajar con una base de c贸digo grande, a menudo se encontrar谩 en situaciones en las que el valor que desea devolver (o pasar) casi coincide con el tipo esperado. Se necesita tiempo y esfuerzo para encontrar la causa de la falta de coincidencia de tipos , y tiene prisa ... por lo que decide utilizar la conversi贸n de tipos.


Sin embargo, al hacer esto, est谩s rompiendo el contrato sagrado . SIEMPRE es mejor asignar tiempo y comprender por qu茅 los tipos no coinciden que utilizar la conversi贸n de tipos. Es muy probable que alg煤n error de tiempo de ejecuci贸n se esconda debajo de la superficie.


No mientas Obedece tus contratos.


Se preciso


Los tipos son documentaci贸n. Al documentar una funci贸n, 驴no desea transmitir tanta informaci贸n como sea posible?


 //   function getUser(id) { /* ... */ } //     : name  age function getUser(id) { /* ... */ } //  id       id , //     : name  age. //     undefined. function getUser(id) { /* ... */ } 

驴Qu茅 comentario para la funci贸n getUser gustar铆a m谩s? Cuanto m谩s sepa que regresa una funci贸n, mejor. Por ejemplo, sabiendo que puede regresar undefined , puede escribir un bloque if para verificar si el objeto que devolvi贸 la funci贸n est谩 definido antes de solicitar las propiedades de este objeto.


Exactamente lo mismo con los tipos: cuanto m谩s exactamente se describe un tipo, m谩s informaci贸n transmite.


 function getUserType(id: number): string { /* ... */ } function getUserType(id: number): 'standard' | 'premium' | 'admin' { /* ... */ } 

La segunda versi贸n de la funci贸n getUserType mucho m谩s informativa y, por lo tanto, la persona que llama se encuentra en una situaci贸n mucho m谩s conveniente. Es m谩s f谩cil procesar el valor si probablemente sabe (contratos, 驴recuerda?) Que ser谩 una de las tres l铆neas dadas, y no cualquier l铆nea. Para comenzar con lo que sabe con certeza: un valor no puede ser una cadena vac铆a.


Consideremos un ejemplo m谩s real. El tipo de State describe el estado del componente que solicita algunos datos del backend. 驴Es este tipo exacto?


 interface State { isLoading: boolean; data?: string[]; errorMessage?: string; } 

Un cliente que usa este tipo debe manejar una combinaci贸n poco probable de valores de propiedades estatales. Por ejemplo, una situaci贸n es imposible cuando las propiedades data y errorMessage se definen simult谩neamente: una solicitud de datos puede tener 茅xito o fallar.


Podemos hacer que el tipo sea mucho m谩s preciso con la ayuda de tipos de uni贸n discriminados :


 type State = | { status: 'loading' } | { status: 'successful', data: string[] } | { status: 'failed', errorMessage: string }; 

Ahora el cliente que usa este tipo tiene mucha m谩s informaci贸n: ya no necesita procesar combinaciones incorrectas de propiedades.


Se preciso. Pase tanta informaci贸n como sea posible sobre sus tipos.


Comience con tipos


Dado que los tipos son tanto un contrato como una documentaci贸n, son excelentes para dise帽ar sus funciones (o m茅todos).


Hay muchos art铆culos en Internet que aconsejan a los programadores que piensen antes de escribir el c贸digo . Comparto completamente este enfoque. La tentaci贸n de saltar directamente al c贸digo es genial, pero esto a menudo conduce a malas decisiones. Pasar un poco de tiempo pensando en la implementaci贸n siempre vale la pena.


Los tipos son extremadamente 煤tiles en este proceso. Pensar lleva a la creaci贸n de firmas de tipos de funciones relacionadas con la resoluci贸n de su problema. Y eso es genial, porque te enfocas en lo que hacen tus funciones, en lugar de pensar en c贸mo lo hacen.


React JS tiene el concepto de componentes de orden superior (HOC). Estas son funciones que extienden el componente dado de alguna manera. Por ejemplo, puede crear un componente de orden superior withLoadingIndicator que agrega un indicador de carga a un componente existente.


Escribamos una firma de tipo para esta funci贸n. La funci贸n acepta una entrada de componente y tambi茅n devuelve un componente. Para representar un componente, podemos usar el tipo React ComponentType .


ComponentType es un tipo gen茅rico que se parametriza por el tipo de propiedades del componente. withLoadingIndicator acepta un componente y devuelve un nuevo componente que muestra el componente original o el indicador de carga. La decisi贸n sobre qu茅 mostrar se basa en el valor de la nueva propiedad l贸gica: isLoading . Por lo tanto, el componente devuelto necesita las mismas propiedades que el original, solo se agrega la nueva propiedad isLoading .


Finalizaremos el tipo. withLoadingIndicator acepta un componente de tipo ComponentType<P> , donde P denota el tipo de propiedad. withLoadingIndicator devuelve un componente con propiedades avanzadas de tipo P & { isLoading: boolean } .


 const withLoadingIndicator = <P>(Component: ComponentType<P>) : ComponentType<P & { isLoading: boolean }> => ({ isLoading, ...props }) => { /* ... */ } 

Al tratar los tipos de funciones, nos vimos obligados a pensar en lo que estar谩 en su entrada y en la salida. En otras palabras, tuvimos que dise帽ar una funci贸n . Escribir su implementaci贸n ahora es f谩cil.


Comience con los tipos. Deje que los tipos lo obliguen a dise帽ar primero, y solo luego escriba la implementaci贸n.


Toma rigor


Los primeros tres mandamientos requieren que prestes especial atenci贸n a los tipos. Afortunadamente, al resolver este problema, no tiene que hacer todo usted mismo; a menudo, el compilador TypeScript le informar谩 cu谩ndo sus tipos est谩n mintiendo o cuando no son lo suficientemente precisos.


Puede ayudar al compilador a hacerlo a煤n mejor si incluye el indicador --strict . Este es un meta indicador que --noImplicitAny todas las opciones estrictas de verificaci贸n de tipos: --noImplicitAny , --noImplicitThis , --alwaysStrict , --strictBindCallApply , --strictNullChecks , --strictFunctionTypes y --strictPropertyInitialization .


驴Qu茅 hacen las banderas? En t茅rminos generales, su inclusi贸n conduce a un aumento en el n煤mero de errores de compilaci贸n de TypeScript. Y esto es bueno! M谩s errores de compilaci贸n: m谩s ayuda del compilador.


Veamos c贸mo activar el indicador --strictNullChecks ayuda a detectar un falso en el c贸digo.


 function getUser(id: number): User { if (id >= 0) { return { name: 'John', age: 12 }; } else { return undefined; } } 

El tipo getUser asegura que la funci贸n siempre devuelve un objeto de tipo User . Sin embargo, observe la implementaci贸n: 隆una funci贸n tambi茅n puede volver undefined !


Afortunadamente, habilitar el indicador --strictNullChecks produce un error de compilaci贸n:


 Type 'undefined' is not assignable to type 'User'. 

El compilador TypeScript detecta falsedades. Para deshacerse de este error, honestamente diga toda la verdad:


 function getUser(id: number): User | undefined { /* ... */ } 

Acepte el rigor de la verificaci贸n de tipos. Deje que el compilador lo proteja de los errores.


Mantenerse al d铆a


TypeScript se est谩 desarrollando a un ritmo muy r谩pido. Se lanza un nuevo lanzamiento cada dos meses. Cada versi贸n trae mejoras significativas en el lenguaje y nuevas caracter铆sticas.


A menudo sucede que las nuevas caracter铆sticas del lenguaje le permiten definir tipos con mayor precisi贸n y verificarlos m谩s estrictamente.


Por ejemplo, en la versi贸n 2.0 se introdujeron los Tipos de Uni贸n Discriminada (los mencion茅 en el mandamiento Sea preciso ).


La versi贸n 3.2 introdujo el indicador del compilador --strictBindCallApply , que incluye la escritura correcta para las funciones de --strictBindCallApply , call y apply .


La versi贸n 3.4 mejor贸 la inferencia de tipos en funciones de orden superior , lo que facilit贸 el uso de tipos exactos al escribir c贸digo en un estilo funcional.


Mi posici贸n es que conocer las caracter铆sticas del lenguaje introducidas en las versiones recientes de TypeScript realmente vale la pena. A menudo, esto puede ayudarlo a seguir los otros cuatro mandamientos de la lista.


Un buen punto de partida es la hoja de ruta oficial de TypeScript . Tambi茅n ser谩 bueno revisar regularmente la secci贸n TypeScript en Microsoft Devblog , ya que todos los anuncios de lanzamiento van all铆.


Mant茅ngase actualizado con las nuevas caracter铆sticas del lenguaje y deje que este conocimiento trabaje para usted.


Resumen


Espero que encuentre 煤til la lista. Como siempre y en todo, uno no debe seguir ciegamente estos mandamientos. Pero creo firmemente que estas reglas te har谩n un mejor desarrollador de TypeScript.


Estar茅 encantado de ver tus pensamientos sobre este tema en los comentarios.


Bono


驴Te ha gustado este art铆culo sobre TypeScript? Estoy seguro de que tambi茅n le gustar谩 este PDF gratuito: 10 errores de desarrollo de TypeScript que hacen que su c贸digo sea inseguro.

Source: https://habr.com/ru/post/461565/


All Articles