20

Cómo tipar componentes en React con TypeScript

49149Puntos

hace 3 años

¡Empieza a tipar tus componentes de React con TypeScript!

Ya te hablé un poco del porqué es una gran idea empezar a tipar tus componentes con PropTypes y algunas de sus ventajas a la hora de desarrollar con ellos. Ahora es el turno de una de sus alternativas: TypeScript.

TypeScript no es un lenguaje nuevo, sino un superset de JavaScript, el cual le da superpoderes para que se vuelva un lenguaje fuertemente tipado.

Cuando combinas el poder de React con el de TypeScript obtienes una excelente dupla para desarrollar aplicaciones web con las mejores prácticas. Esto gracias a que ahora tus proyectos proyectos serán auto descriptivos desde un inicio (siempre y cuando elabores un buen tipado dentro de tus componentes).

¿Cómo usar TypeScript en React?

Existen un par de formas de empezar o agregar TS a un proyecto de React:

  • 1️⃣ Creando tu proyecto con npx
npx create-react-app my-app --template typescript

💡 El flag --template prepara todo un ambiente para que desarrolles con TS y React desde 0, te recomiendo usarlo en proyectos pequeños

  • 2️⃣ Agregando TS a un proyecto ya existente

Si ya tienes un proyecto inicializado con webpack y quieres agregar TS, solo debes instalarlo con NPM o Yarn,junto con su loader como dependencia de desarrollo:

# NPM
npm install --save-dev typescript ts-loader`

# Yarn

yarn add typescript ts-loader --dev


Después de esto procedes a añadirlo en Webpack y lo configuras de la siguiente forma:

```js
// webpack.config.js
const path = require("path");

module.exports = {
  entry:"./src/index.js",
  module: {
    // Agregas como regla usar el loader de typescript    rules: [
      ...{
        test: /\.tsx?$/,
        use:"ts-loader",
        exclude: /node_modules/,
      },
    ],
  },
  resolve: {
    // Al usar ts para tu proyecto debes agregar las extensiones// .ts y .tsx dentro del array de extensiones    extensions: [".tsx", ".ts", ".js"],
  },
  output: {
    filename:"bundle.js",
    path: path.resolve(__dirname, "dist"),
  },
};

Aunque esto no será suficiente para que puedas empezar a desarrollar con TS, ya que también necesitas un archivo de configuración llamado tsconfig.json:

{
  "compilerOptions": {
    "outDir": "./dist/",
    "noImplicitAny": true,
    "module": "es6",
    "target": "es5",
    "jsx": "react",
    "allowJs": true,
    "moduleResolution": "node"
  }
}

💡 Puedes seguir el paso a paso de una manera más fluida en esta clase del curso práctico de webpack

TypeScript en acción

En otra entrada ya vimos como funcionan las Proptypes recreando un componente del blog de Platzi. Ahora vas a construir la vista de la card de los nuevos curso (aunque vamos a customizarla un poco para darle un toque especial).

💡 Para efectos prácticos del ejemplo puedes usar npx create-react-app --template typescript

Elementos de la card

Antes de entrar de lleno al código, debes ver que props necesitará el componente y para ello puedes analizarlo visualmente, aquí abajo lograrás ver de manera más clara los elementos 👇🏻

PropType
imgstring
namestring
dateDate
teacherTeacher
levelstring
ratingnumber
classesnumber
addToPathMouseEventHandler
addToFavoritesMouseEventHandler

Como te mencioné antes, vas a agregar algunos features a la card para hacerla más interesante y así poder experimentar un poco más con TypeScript . Para no extendernos tanto, te explico brevemente que el prop de teacher va a ser un tipo que definirás, ya que este va a tener internamente otras 2 propiedades: name y img

Por otro lado, las últimas dos funciones tienen que ser de un tipo que viene por defecto en React, llamado MouseEventHandler; el cual, como su nombre lo indica, desempeña su función para tipar todo manejador de eventos desencadenados por el mouse.

En la documentación oficial puedes encontrar más información sobre más de ellos

Construyendo componentes con TS

Una vez tengas todo el setup de tu proyecto, empieza creando el componente Course.jsx, el cual tendrá la siguiente estructura:

// src/components/Course.jsxexportconst Course = ({
  img,
  name,
  date,
  teacher,
  rating,
  classes,
  level,
  addToFavorite,
  addToPath,
}: {
  // Una de las formas de tipar las props una por una es dentro de un objeto separado// por dos puntos
  img: string,
  name: string,
  date?: Date,
  // Los parámetros opcionales como date deben tener un ? antes de los dos puntos// al no tener el signo de interrogación TS los toma como parámetros obligatorios
  teacher: { name: string, img?: string },
  // Se puede definir la estructura de los objetos con el tipado de esta forma
  rating: number,
  classes: number | string,
  // Cuando una prop puede ser de dos o más tipos usa el operador | (or) para especificarlos
  level: string,
  addToFavorite: MouseEventHandler,
  addToPath: MouseEventHandler,
  // Los event handlers tienen un tipo especial dentro de React
}) => {
  return (
    <div className="course">
      <div className="course--body">
        <div className="course-img">
          <img src={img} alt={name} />
        </div>
        <div className="course-name">
          <p>{name}</p>
        </div>
        <div className="course-teacher">
          <p>Por {teacher.name}</p>
          <div className="teacher-img">
            <img src={teacher.img} alt={teacher.name} />
          </div>
        </div>
      </div>
      <div className="course--footer">
        <div className="course--details">
          <div className="course-classes-level">
            <span className="course-classes">{classes} clases</span>
            <span className="course-level">Nivel {level}</span>
          </div>
          <div className="course-year-rating">
            <span className="course-rating">{"⭐".repeat(rating)}</span>
            <span className="course-year">{date?.getFullYear()}</span>
          </div>
        </div>
        <div className="course--buttons">
          <button className="button-blue" onClick={addToPath}>
            + Agregar a mis rutas
          </button>
          <button className="button-yellow" onClick={addToFavorite}>
            ⭐ Favorito
          </button>
        </div>
      </div>
    </div>
  );
};
// Esta es la estructura que utilicé, al menos para que tuviera una buena vista la card

⚠️ Cuando pasas una prop diferente a la esperada u omites el asignar una prop que no es opcional, puede hacer que tu App no compile y te muestre un error, especificándote el lugar que causa la detención de la misma

Una recomendación que te doy es que cuando tengas muchas props (como en este caso) prefieras hacer tus propios tipos, de la siguiente forma:

// src/components/Course.tsxtype Teacher = {
  name: string,
  img?: string,
}

type CourseProps = {
  img: string,
  name: number,
  classes?: number,
  date: Date,
  teacher: Teacher,
  level: string,
  addToFavorite: MouseEventHandler,
  addToPath: MouseEventHandler
}

exportconst Course = ({
  img,
  name,
  date,
  teacher,
  rating,
  classes,
  level,
  addToFavorite,
  addToPath } : CourseProps ) => {...}

Puedes optar por usar interface o type, pero depende de ti siempre elegir la mejor opción, en esta clase puedes encontrar el uso de las interfaces

Ya con los estilos aplicados, así quedará la card con TS:

Card course react ts

💻 Aquí en el codepen está el código completo
📖 Repositorio de Github con el código completo

Cómo dominar TypeScript

Es bien sabido que JavaScript tiene unas características un tanto curiosas y puede hacer que tus aplicaciones lleguen a tener errores por olvidar hacer las validaciones correctas con sus tipos, aquí es donde TS viene a salvar el día disminuyendo estos y más problemas.

No te agobies por no saber por donde empezar, aquí abajo te dejo una serie de cursos para que aprendas a utilizar TS en proyectos reales y pienses en pasarte al lado azul 😉

Leonardo de los angeles
Leonardo de los angeles
LeoCode0

49149Puntos

hace 3 años

Todas sus entradas
Escribe tu comentario
+ 2
7
30000Puntos
3 años

¿Habrá curso de React con TypeScript? 👀

3
49149Puntos
3 años

El Curso Práctico de Webpack integra TS y la saga de cursos de Next JS se manejan proyectos con React y TS 😄

10
216912Puntos
3 años

Si lo quieren, yes, why not 💪

3
30000Puntos
3 años

Estaría increíble!