null, undefined y ausencia en TypeScript | Nicolás Garzón
null
undefined
strictNullChecks
Texto
Copiar null → ausencia decidida o explícita
undefined → todavía no existe, no fue proporcionado o no produjo valor
ausente → la propiedad no está presente en el objetoCon comprobación estricta:
TypeScript
Copiar let name: string = "Nicolás" ;
name = null ;
name = undefined ; TypeScript
Copiar let name: string | null = null ; TypeScript
Copiar type SelectedProduct = Product | null ; Puede comunicar que una búsqueda terminó correctamente, pero no existe una selección.
TypeScript
Copiar const selectedProduct: SelectedProduct = null ; TypeScript
Copiar let result: Product | undefined ; Puede comunicar que todavía no se asignó o que una búsqueda no encontró resultado, según el contrato.
Métodos como Map.get retornan T | undefined porque una clave puede no existir.
TypeScript
Copiar type User = {
name: string ;
phone? : string ;
} ; El objeto puede no incluir phone.
TypeScript
Copiar function printPhone ( user: User) {
user. phone;
} La lectura debe contemplar ausencia.
TypeScript
Copiar type OptionalPhone = {
phone? : string ;
} ;
type PresentPhone = {
phone: string | undefined ;
} ; Son contratos diferentes:
TypeScript
Copiar const first: OptionalPhone = { } ;
const second: PresentPhone = {
phone: undefined ,
} ; En el segundo, la clave debe existir aunque su valor sea undefined.
Sin esta regla, TypeScript suele permitir:
TypeScript
Copiar const user: OptionalPhone = {
phone: undefined ,
} ; Con exactOptionalPropertyTypes, una propiedad opcional significa realmente “ausente o string”, salvo que añadas undefined de forma explícita.
TypeScript
Copiar type User = {
phone? : string | undefined ;
} ; Activa este flag cuando la presencia de la clave tiene significado y tu proyecto está preparado para esa precisión.
TypeScript
Copiar function greet ( name? : string ) {
return name === undefined
? "Hola"
: ` Hola, ${ name} ` ;
} Dentro de la función, name es string | undefined.
Un parámetro opcional debe aparecer después de los requeridos, salvo patrones particulares con rest u overloads.
TypeScript
Copiar function greet ( name = "Invitado" ) {
return ` Hola, ${ name} ` ;
} El parámetro se trata como string dentro del cuerpo.
El llamador puede omitirlo o pasar undefined para usar el default:
TypeScript
Copiar greet ( ) ;
greet ( undefined ) ; Pasar null no activa el valor por defecto.
TypeScript
Copiar const city = user. address?. city; Si address es nullish, el resultado es undefined.
TypeScript
Copiar string | undefined No cambia permanentemente el tipo de user.address fuera de la expresión.
TypeScript
Copiar const normalized = user. name
?. trim ( )
. toLowerCase ( ) ; El chain se detiene ante null o undefined en la parte opcional. No protege contra cualquier error de las operaciones posteriores.
TypeScript
Copiar const quantity = inputQuantity ?? 1 ; Usa el fallback únicamente cuando el valor es null o undefined.
TypeScript
Copiar const quantityWithOr = inputQuantity || 1 ; Cuando esos valores son válidos, utiliza ??.
TypeScript
Copiar function printName ( name: string | null ) {
if ( name === null ) {
return ;
}
console . log ( name. toUpperCase ( ) ) ;
} Después del guard, name es string.
TypeScript
Copiar if ( value == null ) {
} Este es uno de los pocos usos deliberados de igualdad flexible: null == undefined es true y otros valores no son iguales a null.
Sé consistente y documenta la intención si la regla de lint permite esta forma.
TypeScript
Copiar if ( name) {
console . log ( name. toUpperCase ( ) ) ;
} Elimina null, undefined y también el string vacío.
Si "" es un valor válido, esta condición mezcla ausencia con contenido vacío.
TypeScript
Copiar if ( name !== null ) { } TypeScript
Copiar const input = document. querySelector ( "input" ) ! ; El ! elimina null y undefined para el checker, pero no verifica que el elemento exista.
Si el selector falla, el runtime recibe null y una operación posterior puede lanzar.
TypeScript
Copiar const input = document. querySelector ( "input" ) ;
if ( ! input) {
throw new Error ( "Input was not found" ) ;
} TypeScript
Copiar const token = localStorage. getItem ( "token" ) ! ; El valor puede no existir. La assertion elimina una posibilidad real.
TypeScript
Copiar const token = localStorage. getItem ( "token" ) ;
if ( token === null ) {
return redirectToLogin ( ) ;
} TypeScript
Copiar class Service {
private client! : Client;
initialize ( client: Client) {
this . client = client;
}
} El ! después del nombre de la propiedad promete que será inicializada por otra ruta.
No es igual a value!, aunque ambos piden al checker confiar.
Si initialize no ocurre, el objeto puede fallar en runtime. Constructor injection suele ofrecer un contrato más fuerte.
TypeScript
Copiar const products: Product[ ] = [ ] ;
const first = products[ 0 ] ; Sin noUncheckedIndexedAccess, el tipo puede ser Product aunque el array esté vacío.
TypeScript
Copiar Product | undefined El checker modela que cualquier índice puede faltar.
TypeScript
Copiar const product = products. find (
( candidate) => candidate. id === productId,
) ; El retorno es Product | undefined, incluso cuando crees que el dato debería existir.
Puedes modelar contratos distintos:
TypeScript
Copiar function findProduct ( id: string ) : Product | undefined ;
function requireProduct ( id: string ) : Product; JSON no conserva propiedades con valor undefined dentro de objetos:
TypeScript
Copiar JSON . stringify ( {
phone: undefined ,
} ) ;
Ausente y undefined pueden terminar con la misma representación JSON, mientras null sí se conserva.
Define el formato de intercambio de forma explícita.
TypeScript
Copiar type SearchResult< T > =
| { found: true ; value: T }
| { found: false } ;
function findById < T extends { id: string } > (
values: readonly T [ ] ,
id: string ,
) : SearchResult< T > {
const value = values. find (
( candidate) => candidate. id === id,
) ;
return value === undefined
? { found: false }
: { found: true , value } ;
} El discriminante evita depender de la interpretación ambigua de null o undefined.
Desactivar strictNullChecks para evitar guards.
Confundir propiedad opcional con propiedad requerida de valor undefined.
Utilizar || cuando 0, false o string vacío son válidos.
Usar truthiness y eliminar valores legítimos.
Añadir ! sin una garantía runtime.
Confundir non-null assertion con definite assignment assertion.
Esperar que un default aplique ante null.
Ignorar que find e índices pueden no producir valor.
Usar null y undefined sin definir su significado en el dominio.
null y undefined son tipos separados bajo strictNullChecks.
Una propiedad opcional puede estar ausente.
T | undefined puede exigir que la clave exista.
exactOptionalPropertyTypes conserva esa diferencia.
Optional chaining produce undefined cuando se detiene.
?? solo reemplaza valores nullish.
Truthiness puede eliminar 0, false y string vacío.
! es una promesa al checker, no una comprobación.
Las APIs que pueden fallar deben reflejar ausencia en su contrato.
¿Cuál es la diferencia entre phone?: string y phone: string | undefined?
Respuesta La primera permite que la propiedad no exista. La segunda exige que la clave esté presente, aunque su valor pueda ser undefined.
Arrays, readonly arrays y tuples aplica el sistema de tipos a colecciones ordenadas y posiciones conocidas.