Expandiendo la interfaz Request de Express con .d.ts
Tags: express, backend, node, typescript
Published: 2023-05-26 16:15:35

Hace poco me enfrente a una situación en la cual tenía un proyecto en Express con Typescript y uno de mis middlewares, especificamente el de autorización, debía obtener, de un JWT, el email del usuario y pasarlo al controlador de alguna forma.

Quería que dicho email llegara al controlador ya con el campo email dentro del objeto request de express con el fin de poder desestructurarlo de una manera más sencilla pero al intentar hacerlo me encontraba con el siguiente error:

![Error 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/le2mkyp8n6ny07u6f815.png)

¿Porqué sucede esto? Estamos intentando agregar un campo desconocido para el parámetro request de express, debemos recordar que estos campos están definidos en interfaces o tipos que el mismo express nos provee cuando instalamos la dependencia, por lo tanto, debemos lograr que dicha interfaz contemple el valor que queremos suministrarle a request y de esta forma el compilador de typescript nos permitirá agregar el campo que necesitamos ya que lo reconocerá dentro de la interfaz. 

## Usando archivos .d.ts

Para lograr el anterior objetivo podemos hacer uso de los archivos _definition types_ de typescript. Estos archivos son aquellos que tienen como extensión `.d.ts` y son utilizados para definir tipos de datos y algunos casos de uso podrían ser:

- Definir tipos de datos de librerías que están escritas en Javascript y se necesita que el compilador de typescript reconozca los datos de dicha librería. Un ejemplo de esto es el repositorio de [definitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped).

- Migrar aplicaciones de Javascript a Typescript progresivamente. Los archivos `.d.ts` nos facilitan la migración de aplicaciones de Javascript a typescript al permitirnos centralizar los tipos de datos en archivos específicos, obteniendo así una fuente de documentación viva a la cual remitirnos con facilidad durante el proceso de migración.

> Debemos resaltar que los archivos `.d.ts` no generan código de salida por lo tanto estos no terminaran en el código .js final.  

En síntesis, un archivo definition type `.d.ts` nos facilita definir tipos tanto de nuestras aplicaciones como de librerías de terceros como lo veremos a continuación.

## Extendiendo request de Express

Para poder solucionar el error mostrado anteriormente, cuando intentábamos crear un campo en el objeto request de express, debemos primero crear una carpeta que contendrá nuestros _definitions types_. En mi caso generé una carpeta `@types` en mi carpeta de configuración de express y dentro de ella sub carpetas para cada librería o archivo que necesite un `.d.ts`: 

```
- src
  ... otros archivos
  - config
    - @types 
      - express
        - custom.d.ts
      ... otras carpetas para definición de tipos
```

Dentro de este archivo `custom.d.ts` debo generar el siguiente código: 

```
declare namespace Express {
  interface Request {
    user: {
      email: string;
    };
  }
}
```

Puedes observar que estamos haciendo uso de `declare namespace Express` y dentro de las llaves definimos una interface de typescript, en este caso con el nombre Request, para agregarle los campos que necesitamos.

Al hacer uso de `declare namespace Express` estamos declarando un espacio de nombres, en este caso para la librería de Express, esto nos permite decirle al compilador de typescript que todo lo que declaremos dentro de este espacio corresponde a la librería de Express y de esta forma evitar colisiones, mejorar la modularidad de nuestro código y estructurar mejor las definiciones de tipos.

Ahora bien, debemos remitirnos a nuestro archivo package.json para definir la ubicación de nuestros tipos de datos y para ello debemos hacer uso de la propiedad _"compilerOptions"_ así:

```
{
  ... 
  "compilerOptions": {
    "typeRoots": [
      "./src/config/@types"
    ]
  },
}
```
De esta forma el error desaparecerá y podremos agregar los campos que necesitemos al request de Express y así typescript podrá compilar nuestro código sin problemas.

Esto es todo. Espero sea de utilidad. 

Cheers! :)