React + Typescript: conceptos básicos Props

Un gran beneficio de pasar de JavaScript a TypeScript con React, es el de poder definir un contrato tipado de las propiedades que expone cada componente.

Esto lo cubría en cierta manera React con sus prop types pero ésta es una solución limitada que además añade peso extra a tu bundle.

En este vídeo vamos a ver como usar TypeScript para definir tus propiedades.

Manos a la obra

Partimos de un codesandbox eligiendo la plantilla de TypeScript, partimos del siguiente código:

./app.tsx

import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

Vamos a crear un componente que llamaremos MuestraNombre en el que recibiremos como propiedad un nombre y un apellido, si no aplicamos tipado tendríamos algo así como:

./app.tsx

import "./styles.css";

+ const MuestraNombre = (props) => {
+  return (
+    <h1>{props.nombre} {props.apellidos}</h1>
+  )
+ }

export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

Y podríamos usarlo tal cual:

import "./styles.css";

 const MuestraNombre = (props) => {
  return (
    <h1>{props.nombre} {props.apellidos}</h1>
  )
 }

export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
+     <MuestraNombre nombre="Jose" apellidos="García Pérez"/>
    </div>
  );
}

En principio para este componente sencillo parece que todo va bien, pero..

  • ¿Qué pasa si nos equivocamos al escribir el nombre de una de las propiedades? Tendríamos un error en tiempo de ejecución.

  • Cómo consumidor de ese componente, ¿Cómo se que propiedades admite? Tendría que meterme dentro del componente e investigarlo.

  • Otro punto interesante es saber que tipo de dato está esperando, podría pasarle un objeto cuando lo que está esperando es un string.

  • Y para finalizar, que pasa si quiero hacer un valor opcional, o que tenga un valor por defecto si no esta informado....

TypeScript al rescate.

Lo primero vamos a pasar a definir el contrato, esto lo hacemos con una interfaz de TypeScript:

interface Props {
  nombre: string;
  apellidos: string;
}

Ahora puedes pensar Vale... hablamos de no añadir peso y ya estamos metiendo código de más lo curioso de las interfaces es que sólo las ves en tiempo de desarrollo, una vez que el código se transpila, éstas desaparecen del código Javascript final, dejando cero huella en el peso de tu aplicación.

Ya que tenemos el contrato, el siguiente paso es decirle a nuestro componente que use estas Props. Aquí tenemos dos opciones:

La primera directamente podemos decir que el parámetro props tiene el tipo Props que acabamos de definir:

interface Props {
  nombre: string;
  apellidos: string;
}

- const MuestraNombre = (props) => {
+ const MuestraNombre = (props : Props) => {

Ahora si nos vamos al sitio donde estamos usando el componente y borramos una de las propiedades o le cambiamos el nombre veremos que el editor nos marcará el error.

Esta aproximación esta muy bien, pero dependiendo de lo que necesitemos igual echamos de menos:

  • Contar con la propiedad children de un componente.
  • Tipar lo que devuelve un componente, de forma que si por ejemplo se me olvida poner el return de mi componente, no me lo de como válido.

Para hacer esto, los typings de React nos ofrecen el tipo React.FC (React Functional Component), cómo quedaría esto en código:

+ import React from 'react';
import "./styles.css";

interface Props {
  nombre: string;
  apellidos: string;
}

- const MuestraNombre = (props : Props) => {
+ const MuestraNombre: React.FC<Props> = (props) => {

Fijate que aquí estamos usando un genérico para alimentar el tipo de las props, ¿Por qué? porque a la variable props le metemos el tipo de interfaz Props más la propiedad children de los componentes de React.

Por otro lado si ahora eliminamos el return de MuestraNombre o cambiamos el tipo del return obtendremos un error.

¿Te apuntas a nuestro máster?

Si te ha gustado este ejemplo y tienes ganas de aprender Front End guiado por un grupo de profesionales ¿Por qué no te apuntas a nuestro Máster Front End Online Lemoncode? Tenemos tanto edición de convocatoria con clases en vivo, como edición continua con mentorización, para que puedas ir a tu ritmo y aprender mucho.