Saltar al contenido principal

Manejo de valores null y undefined en condiciones WHERE

Traducción Beta No Oficial

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

En condiciones 'WHERE', los valores null y undefined no son estrictamente válidos en TypeORM.

TypeScript prohíbe pasar valores null conocidos en tiempo de compilación (cuando tienes activado strictNullChecks en tsconfig.json). El comportamiento predeterminado es que los valores null y undefined encontrados durante ejecución generen un error.

El manejo de valores null y undefined se puede personalizar mediante la opción de configuración invalidWhereValuesBehavior en las opciones de tu fuente de datos. Esto aplica a operaciones de alto nivel como búsquedas (find), métodos de repositorio y métodos de EntityManager (update, delete, softDelete, restore).

advertencia

Esta configuración no afecta los métodos .where(), .andWhere() u .orWhere() de QueryBuilder. QueryBuilder es una API de bajo nivel donde los valores null/undefined pasan sin modificaciones. Usa el operador IsNull() o condiciones parametrizadas en QueryBuilder para manejo explícito de null.

Comportamiento predeterminado

Por defecto, TypeORM lanza un error cuando encuentra valores null o undefined en condiciones WHERE. Esto previene resultados inesperados y ayuda a detectar errores potenciales temprano:

// Both queries will throw an error
const posts1 = await repository.find({
where: {
text: null,
},
})
// Error: Null value encountered in property 'text' of a where condition.

const posts2 = await repository.find({
where: {
text: undefined,
},
})
// Error: Undefined value encountered in property 'text' of a where condition.

Para buscar valores null en condiciones WHERE, usa el operador IsNull (para detalles ver Find Options):

const posts = await repository.find({
where: {
text: IsNull(),
},
})

Configuración

Puedes personalizar el manejo de valores null y undefined mediante la opción invalidWhereValuesBehavior en tu configuración de fuente de datos:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "ignore" | "sql-null" | "throw",
undefined: "ignore" | "throw",
},
})

Opciones para null

El comportamiento para null admite tres valores:

'ignore'

Los valores null de JavaScript se ignoran y la propiedad se omite:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "ignore",
},
})

// This will return all posts, ignoring the text property
const posts = await repository.find({
where: {
text: null,
},
})

'sql-null'

Los valores null de JavaScript se transforman en condiciones SQL NULL:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "sql-null",
},
})

// This will only return posts where the text column is NULL in the database
const posts = await repository.find({
where: {
text: null,
},
})

'throw' (predeterminado)

Los valores null de JavaScript lanzan un TypeORMError:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "throw",
},
})

// This will throw an error
const posts = await repository.find({
where: {
text: null,
},
})
// Error: Null value encountered in property 'text' of a where condition.
// To match with SQL NULL, the IsNull() operator must be used.
// Set 'invalidWhereValuesBehavior.null' to 'ignore' or 'sql-null' in data source options to skip or handle null values.

Opciones para undefined

El comportamiento para undefined admite dos valores:

'ignore'

Los valores undefined de JavaScript se ignoran y la propiedad se omite:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
undefined: "ignore",
},
})

// This will return all posts, ignoring the text property
const posts = await repository.find({
where: {
text: undefined,
},
})

'throw' (predeterminado)

Los valores undefined de JavaScript lanzan un TypeORMError:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
undefined: "throw",
},
})

// This will throw an error
const posts = await repository.find({
where: {
text: undefined,
},
})
// Error: Undefined value encountered in property 'text' of a where condition.
// Set 'invalidWhereValuesBehavior.undefined' to 'ignore' in data source options to skip properties with undefined values.

Nota: Esto aplica solo a valores undefined explícitos, no a propiedades omitidas.

Uso combinado de opciones

Puedes configurar ambos comportamientos de forma independiente:

const dataSource = new DataSource({
// ... other options
invalidWhereValuesBehavior: {
null: "sql-null",
undefined: "throw",
},
})

Esta configuración:

  1. Transformará valores null de JavaScript a SQL NULL

  2. Lanzará errores al encontrar valores undefined

  3. Seguirá ignorando propiedades no proporcionadas en WHERE

Esta combinación es útil cuando necesitas:

  • Ser explícito al buscar valores NULL en la base de datos

  • Detectar errores de programación donde valores undefined podrían filtrarse en tus consultas

Operaciones soportadas

La configuración invalidWhereValuesBehavior aplica a operaciones de alto nivel de TypeORM, no al método .where() directo de QueryBuilder:

Operaciones de búsqueda (Find)

// Repository.find() / findOne() / findBy() / findOneBy()
await repository.find({ where: { text: null } }) // Respects invalidWhereValuesBehavior

// EntityManager.find() / findOne() / findBy() / findOneBy()
await manager.find(Post, { where: { text: null } }) // Respects invalidWhereValuesBehavior

Métodos de Repository y EntityManager

// Repository.update()
await repository.update({ text: null }, { title: "Updated" }) // Respects invalidWhereValuesBehavior

// Repository.delete()
await repository.delete({ text: null }) // Respects invalidWhereValuesBehavior

// EntityManager.update()
await manager.update(Post, { text: null }, { title: "Updated" }) // Respects invalidWhereValuesBehavior

// EntityManager.delete()
await manager.delete(Post, { text: null }) // Respects invalidWhereValuesBehavior

// EntityManager.softDelete()
await manager.softDelete(Post, { text: null }) // Respects invalidWhereValuesBehavior

QueryBuilder con setFindOptions

// setFindOptions goes through the find-options path, so it respects the setting
await dataSource
.createQueryBuilder(Post, "post")
.setFindOptions({ where: { text: null } }) // Respects invalidWhereValuesBehavior
.getMany()

No afectado: QueryBuilder .where()

Los métodos .where(), .andWhere() y .orWhere() de QueryBuilder son APIs de bajo nivel y no se ven afectados por esta configuración. Los valores null y undefined pasan sin modificaciones:

// This does NOT respect invalidWhereValuesBehavior — null passes through as-is
await dataSource
.createQueryBuilder()
.update(Post)
.set({ title: "Updated" })
.where({ text: null })
.execute()

Comportamiento de null y undefined en QueryBuilder .where()

Como QueryBuilder es una API de bajo nivel, los valores null y undefined no son validados ni transformados. Entender su comportamiento es crucial para evitar resultados inesperados.

null en QueryBuilder .where()

Cuando se pasa null como valor en un .where() con sintaxis de objeto, genera una comparación de igualdad SQL contra NULL:

await dataSource
.createQueryBuilder(Post, "post")
.where({ text: null })
.getMany()
// Generates: WHERE post.text = NULL

En SQL, column = NULL es siempre falso — nada equivale a NULL. Esta consulta devolverá cero resultados, lo que casi seguro no es lo que buscabas. Para buscar valores NULL, usa el operador IsNull():

import { IsNull } from "typeorm"

await dataSource
.createQueryBuilder(Post, "post")
.where({ text: IsNull() })
.getMany()
// Generates: WHERE post.text IS NULL

O usa una condición de texto:

await dataSource
.createQueryBuilder(Post, "post")
.where("post.text IS NULL")
.getMany()

undefined en QueryBuilder .where()

Cuando se pasa undefined como valor, aplica el mismo comportamiento — genera WHERE column = NULL, que siempre es falso:

await dataSource
.createQueryBuilder(Post, "post")
.where({ text: undefined })
.getMany()
// Generates: WHERE post.text = NULL
// Returns: zero results

Tabla resumen

ValueHigh-level API (find/repository/manager)QueryBuilder .where()
null with "ignore"Property skipped — no filterWHERE col = NULL — zero results
null with "sql-null"WHERE col IS NULLWHERE col = NULL — zero results
null with "throw" (default)Throws errorWHERE col = NULL — zero results
undefined with "ignore"Property skipped — no filterWHERE col = NULL — zero results
undefined with "throw" (default)Throws errorWHERE col = NULL — zero results
IsNull()WHERE col IS NULLWHERE col IS NULL
consejo

Siempre usa IsNull() cuando quieras buscar valores SQL NULL, sin importar qué API uses. Funciona correctamente tanto en contextos de alto nivel como en QueryBuilder.