4. The quick guide to the best TypeScript tips: Classes, Generics & Utilities

Updated: Aug 2

En TS las clases son tipos donde se pueden utilizar modificadores de tipo para los miembros de las clases. ¿Sabes en qué consisten? 🤓 Fin de la Miniserie de Melt: Quick Guide - TypeScript! 🆃🆂 .

Recopilamos para ti algunos tips útiles de TypeScript!


ℹ️ Antes de seguir leyendo:

Recuerda que este post hace parte de una miniserie, y es probable que algunos temas ya hayan sido explicadas. Así que, te invitamos a revisar los posts anteriores:



__________________________________



TypeScript IV

TALK DE LA SEMANA



Clases

En el post anterior vimos que las interfaces nos permiten construir nuevos tipos a partir de otros tipos al extenderlos, pero TypeScript nos proporciona una construcción diferente para combinar esos tipos existentes


Es decir, es la creación de un tipo que fusiona varios tipos para crear un solo tipo pero con la diferencia que este nuevo tipo infiere todas las propiedades de los otros tipos... 😪 uff, me quedé sin aire. Mejor veamos cómo funciona:

Si existe algún error en el reproductor, puedes ver el video en el siguiente LINK.


Entre las dos formas de combinar tipos (interfaz e intersección), puede que nos parezca que son casi lo mismo, pero en realidad son sutilmente diferentes.


En cualquier caso, con las interfaces podríamos hacer extend desde otros tipos, y nombrar el resultado con un alias de tipo... Digamos que el resultado sería parecido a una intersección, no? Sin embargo, sólo veríamos los problemas una vez corramos el código, y es donde los conflictos marcarían las diferencias:

  • extends solo se puede usar con tipos con miembros estáticamente conocidos

type alphaType = {
  a: string;
}

interface alphaInterface extends alphaType {} // ok

type ComplexType = { a: string } | { a: number };
// error: An interface can only extend an object type or intersection of object types...

interface ComplexInterface extends ComplexType {}
  • Cuando se extiende desde una interfaz principal, no puede crear campos con el mismo nombre que en la interfaz principal, pero con un tipo más amplio:

interface Parent {
    a: string | number;
}

interface Child1 extends Parent {
    a: string; // ok
}
interface Child2 extends Parent {
    a: string | number | boolean; // error
}

Sin embargo, el tipo de intersección:

type IntersectedChild = Parent & {
  a: string | boolean
};
// IntersectedChild will have property 'x' that is an intersection
// of 'string | number' and 'string | boolean', that is a 'string':

type IntersectedChildX = IntersectedChild['x']; // string

Entonces,

  • Cuando se usa extends se heredan todas las implementaciones del padre; sin embargo, la intersección de tipos solo funciona en el nivel de tipo.

  • La intersección de tipos es una operación de tipo, que se realiza con tipos cualquiera y dará un resultado; mientras que extends se limita a interfaces y tipos (y clases) similares a interfaces.

Y esa diferencia suele ser una de las razones principales por las que elegiría uno sobre el otro entre una interfaz y un alias de tipo de un tipo de intersección.



__________________________________



Tipos de unión

El sistema de tipos permite crear nuevos tipos a partir de tipos existentes con: combinaciones.


  • Unión. Es un tipo formado por dos o más, que representan valores que pueden ser any.

| Cuando uno quiere que una variable tenga múltiples tipos usa: Las uniones


Es fácil proporcionar un valor que coincida con un tipo de unión: simplemente proporcione un tipo que coincida con cualquiera de los miembros de la unión y si tiene un valor de un tipo de unión, ¿Cómo trabaja con él?

Si existe algún error en el reproductor, puedes ver el video en el siguiente LINK.


En el ejemplo, podemos conocer que padding tendría que ser de tipo Any para que acepte tanto string como number sin problema:

function padLeft(value: string, padding: any) {
  if(typeof padding === 'number') {
    return Array(padding + 1).join(' ') + value;
  }
  if(typeof padding === 'string'){
    return padding + value;
  }
  throw new Error(`Expected string or number, got '${padding}'.`);
}
padLeft('Hello world', 4); // returns "    Hello world"

Pero cuando reciba, por ejemplo, un booleano el código va fallar:

padLeft('Hello world', true); // throws at runtime

- El tipo NO puede ser any, porque realmente no recibe cualquiera sólo numbers y strings -


La idea es prevenir que de verdad la función pueda recibir cualquiera cuando en realidad sólo necesitamos dos tipos. La alternativa y solución para esta situación es usar una unión ( | ):

function typedPadLeft(value: string, padding: string | number): string {
  if(typeof padding === 'number'){
    return Array(padding + 1).join(' ') + value;
  }
  if(typeof padding === 'string') {
    return padding + value;
  }
  throw new Error('Expected string or number, got '${padding}'.`);
}
typePadLeft('Hello world', 4); // returns "    Hello world"

Y cuando reciba un booleano, el código va informar que: El dato tipo boolean no se le puede asignar a los tipos string o number:

typePadLeft('Hello world', true); //argument type 'bool' is not assignable

Recuerda que:

El Sistema de Tipos es responsable de verificar el tipo de datos de cualquier valor.

Y justamente por eso debemos programar usando en la menor cantidad posible el tipo: any. Acá te dejamos varios ejemplos:

Si existe algún error en el reproductor, puedes ver el video en el siguiente LINK.



Esperamos que esta serie te haya gustado!

_________________________________________________________________________________________


¡Gracias por leer!


📍 Conéctate con nosotros en instagram👇


6 views

Join our newsletter to receive information about latest technologies trends and job offers

Thanks for subscribing!