Sergio Xalambrí
February 26, 2019

# Tipos de datos en React

Hay varias formas de definir que tipos de datos recibe un componente en React, puede ser TypeScript, Flow o PropTypes

Siguiendo con el uso de props vamos a definir como definir a que tipo de dato pertenecen nuestros props.

Esto aunque parece más trabajo ayuda a documentar nuestros componentes para que tanto otros desarrolladores, como nosotros mismos en el futuro, podamos saber que recibe un componente y no encontrarnos con errores.

Hay, como todo en JavaScript, varias formas de definir tipos de datos en React.

## TypeScript

Una forma es usar TypeScript en vez de JavaScript normal, TypeScript es un lenguaje de programación que extiende JavaScript para agregar, entre otras cosas, tipos de datos al lenguaje los cuales son detectados por su compilador para ayudarte a prevenir errores durante el funcionamiento de la aplicación.

    interface Props {
      name?: string;
    }

    function Hello({ name = "Mundo"}: Props) {
      return React.createElement("h1", null, `Hola ${props.name}!`);
    }

En este caso ya que usamos TypeScript es más común usar funcionalidades propias del lenguaje para, por ejemplo, definir valores por defecto a un prop.

> Si querés aprender TypeScript te recomiendo leer su documentación en https://www.typescriptlang.org/.

## FlowType

Similar a TypeScript, FlowType extiende JavaScript para agregar tipos de datos, en este caso solo hace esto. Sus tipos son usados también al momento de compilar para detectar errores.

    type Props {
      name?: string,
    }

    function Hello({ name = "Mundo"}: Props) {
      return React.createElement("h1", null, `Hola ${props.name}!`);
    }

> Si querés aprender FlowType te recomiendo leer su documentación en https://flow.org/.

## PropTypes

PropTypes es la forma propia de React que funciona sin necesidad de compilar y de usar otro lenguaje de programación. Originalmente venía incluído en el mismo React, actualmente dada la popularidad de TypeScript y FlowType se separó en una librería externa para reducir el tamaño de React, así solo quienes usen PropTypes lo cargan.

Para cargarlo en nuestro proyecto es igual que hicimos con React y ReactDOM.

    <script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.2/prop-types.min.js"></script>

Una etiqueta `<script>` con el link para cargarlo desde un CDN.

Ahora vamos a tipar nuestro componente, para eso vamos a agregarle una propiedad estática llamada `propTypes` que va a ser un objeto donde cada key es un prop y su valor es el tipo de dato.

    function Hello(props) {
      return React.createElement("h1", null, `Hola ${props.name}!`);
    }

    Hello.propTypes = {
      name: PropTypes.string
    };

    Hello.defaultProps = {
      name: "Mundo"
    };

Con esto acabamos de definir que el prop `name` debe ser un string. Si ahora pasamos cualquier otro valor React nos va a mostrar en la consola de nuestro navegador un error de tipo de dato.

Al igual que hay `PropTypes.string` hay muchos otros tipos de datos dependiendo de nuestras necesidades.

PropTypes | Descripción
--- | ---
`array` | Un array normal de JavaScript (`[]`)
`bool` | Un `true` o un `false`
`func` | Una función (normal, arrow, generador o async)
`number` | Un número, tanto entero como con decimales, positivo o negativo
`object` | Un objeto plano de JavaScript (`{}`)
`string` | Una cadena de caracteres
`symbol` | Un símbolo creado con `Symbol()`
`node` | Un nodo, puede ser cualquier hijo válido en React
`element` | Un elemento de React (el resultado de `React.createElement`)
`instanceOf(Class)` | Una instancia de la clase `Class`
`oneOf(['React', 'Redux'])` | Uno de varios valores fijos posibles
`oneOfType([string, number])` | Uno de varios tipos de datos posibles
`arrayOf(number)` | Un array del tipo de dato especificado
`objectOf(number)` | Un objeto cuyos valores sean del tipo de dato especificado
`shape({ name: string })` | Un objeto con la forma específicada
`any` | Cualquier tipo de dato

> Nota: Normalmente `shape` es mejor que `object` u `objectOf` ya que nos permite especificar la forma exacta que debe tener el objeto que vamos a recibir como prop.

Adicionalmente es posible crear PropTypes personalizados para hacer validaciones propias sobre los props. Esto lo veremos más adelante.

### Props Obligatorios

También es posible definir un prop como obligatorio para que, en caso de no estar definido, React muestre un error avisando que es obligatorio.

    function Hello(props) {
      return React.createElement("h1", null, `Hola ${props.name}!`);
    }

    Hello.propTypes = {
      name: PropTypes.string.isRequired
    };

Como vemos, es cuestión de agregar `.isRequired` al tipo de dato para hacerlo obligatorio, otra efecto de esto es que podemos sacar el `defaultProps` ya que al ser obligatorio estamos seguros de que el usuario de nuestro componente va a definir siempre `name` y si no lo hace no nos molesta que falle el componente pues está marcado como obligatorio.

## Palabras finales

Con todo esto nuestro ejemplo pasaría a ser igual es esto:

    function Hello(props) {
      return React.createElement("h1", null, `Hola ${props.name}!`);
    }

    Hello.propTypes = {
      name: PropTypes.string
    };

    Hello.defaultProps = {
      name: "Mundo"
    };

    const element = React.createElement(Hello, { name: "Sergio" });
    const node = document.getElementById("app");

    ReactDOM.render(element, node);

Ya vimos como hacer un componente que use props, definir valores por defecto y ahora especificar el tipo de datos.

En próximos artículos veremos como hacer composición de componentes de React.

###### Read next: Composición de Componentes en React

Una de las mejores cosas de React es poder combinar componentes para crear nuevo componentes más complejos.