Nullable en TypeScript: ¿cómo declarar un tipo que puede ser null?

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

TypeScript y su eterna pregunta: ¿cómo hacer un tipo nullable?

\n\n

¡Hola, colega! Si alguna vez has escrito en TypeScript, seguro te has encontrado con la situación en la que una función puede devolver un valor, o puede que no. O una variable no se inicializa de inmediato. Y aquí surge la pregunta sacramental: ¿cómo declarar un tipo que puede ser null o undefined?

\n\n

Esta pregunta es una de las más populares en Stack Overflow (¡decenas de miles de visitas!), y no es casualidad. TypeScript es estricto, pero justo. No nos permite simplemente asignar null a una variable de tipo string. Y eso es maravilloso, porque nos salva de montones de errores. Pero, ¿qué hacer cuando nullable es parte de la lógica de negocio? Vamos a descubrirlo.

\n\n

En este artículo no solo daremos una respuesta seca. Recorreremos desde lo básico hasta técnicas avanzadas, analizaremos errores comunes y aprenderemos a escribir código que sea seguro y elegante. ¡Allá vamos!

\n\n

Fundamentos: Union Types y Null

\n\n

La forma más simple y directa de hacer un tipo nullable es usar un union type (unión de tipos). Si una variable puede ser un string o null, escribimos así:

\n\n
let userName: string | null = null;\nuserName = "Alicia"; // Ok\nuserName = null;    // También ok\n
\n\n

Lo mismo funciona con undefined. En TypeScript, null y undefined son tipos diferentes (a menos que la bandera --strictNullChecks esté desactivada, pero hablaremos de eso más adelante).

\n\n
let age: number | undefined;\nage = 25;\nage = undefined; // Funciona\n
\n\n

Importante: si usas | null o | undefined, TypeScript te obligará a verificar el valor antes de usarlo. Intentar llamar a un método en un objeto potencialmente null provocará un error de compilación. Esta es la "seguridad" por la que amamos TS.

\n\n

Ejemplo de la vida real: búsqueda de usuario

\n\n
interface User {\n  id: number;\n  name: string;\n}\n\nfunction findUser(id: number): User | null {\n  // ...lógica de búsqueda\n  if (id === 1) {\n    return { id: 1, name: "Iván" };\n  }\n  return null;\n}\n\nconst user = findUser(2);\n// user.name; // ¡Error! 'user' posiblemente es null\nif (user) {\n  console.log(user.name); // Ahora es seguro\n}\n
\n\n

¿Ves? El compilador mismo te sugiere: "Oye, verifica, o te caerás". Esto ahorra horas de depuración.

\n\n

Parámetros y propiedades opcionales (Optional Chaining)

\n\n

A menudo, no solo las variables son nullable, sino también los campos de objetos o los argumentos de funciones. Para esto, TypeScript tiene una sintaxis especial: el modificador opcional (el signo de interrogación ?).

\n\n

Parámetros opcionales de función

\n\n
function greet(name?: string) {\n  if (name) {\n    return `¡Hola, ${name}!`;\n  }\n  return "¡Hola, desconocido!";\n}\n\nconsole.log(greet("Pedro")); // ¡Hola, Pedro!\nconsole.log(greet());       // ¡Hola, desconocido!\n
\n\n

El tipo del parámetro name se convierte automáticamente en string | undefined. Observa: si un parámetro es opcional, no es necesario pasarlo, y TS no se quejará.

\n\n

Propiedades opcionales de interfaces

\n\n
interface Config {\n  url: string;\n  port?: number; // puede ser number o undefined\n}\n\nconst config1: Config = { url: "http://localhost" }; // port está ausente\nconst config2: Config = { url: "http://localhost", port: 3000 };\n
\n\n

Al acceder a config1.port, TypeScript dirá que es number | undefined. Y es correcto: no sabemos si el puerto está definido.

\n\n

Encadenamiento opcional (Optional Chaining) — tu mejor amigo

\n\n

Con la llegada de ES2020 y TypeScript 3.7, tenemos una forma elegante de acceder de forma segura a propiedades anidadas que pueden ser null o undefined. Esto se llama optional chaining

Blogs

Book Recommendations