Saltar al contenido principal

Preguntas frecuentes

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 →

¿Cómo actualizo el esquema de la base de datos?

Una de las principales responsabilidades de TypeORM es mantener tus tablas de base de datos sincronizadas con tus entidades. Existen dos formas de lograrlo:

  • Usa synchronize: true en las opciones del data source:

    import { DataSource } from "typeorm"

    const myDataSource = new DataSource({
    // ...
    synchronize: true,
    })

    Esta opción sincroniza automáticamente tus tablas de base de datos con las entidades proporcionadas cada vez que ejecutas este código. Es ideal durante el desarrollo, pero en producción probablemente no querrás tenerla habilitada.

  • Usa herramientas de línea de comandos y ejecuta la sincronización de esquemas manualmente:

    typeorm schema:sync

    Este comando ejecutará la sincronización del esquema.

La sincronización de esquemas es extremadamente rápida. Si estás considerando desactivar la opción de sincronización durante el desarrollo por problemas de rendimiento, primero verifica qué tan rápido es realmente.

¿Cómo cambio el nombre de una columna en la base de datos?

Por defecto, los nombres de columna se generan a partir de los nombres de las propiedades. Puedes cambiarlos fácilmente especificando la opción name en la columna:

@Column({ name: "is_active" })
isActive: boolean;

¿Cómo puedo establecer un valor predeterminado usando una función como NOW()?

La opción default de las columnas admite funciones. Si pasas una función que devuelve una cadena, TypeORM usará esa cadena como valor predeterminado sin escaparla. Por ejemplo:

@Column({ default: () => "NOW()" })
date: Date;

¿Cómo implementar validación?

La validación no es parte de TypeORM porque es un proceso separado no directamente relacionado con su función. Para validación, usa class-validator - funciona perfectamente con TypeORM.

¿Qué significa "lado propietario" en relaciones o por qué necesitamos @JoinColumn y @JoinTable?

Comencemos con una relación one-to-one. Supongamos dos entidades: User y Photo:

@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number

@Column()
name: string

@OneToOne()
photo: Photo
}
@Entity()
export class Photo {
@PrimaryGeneratedColumn()
id: number

@Column()
url: string

@OneToOne()
user: User
}

Este ejemplo no tiene @JoinColumn, lo cual es incorrecto. ¿Por qué? Para establecer una relación real, necesitamos crear una columna en la base de datos. Debemos crear userId en photo o photoId en user. ¿Pero qué columna debe crearse - userId o photoId? TypeORM no puede decidirlo por ti. Para determinarlo, debes usar @JoinColumn en uno de los lados:

  • Si colocas @JoinColumn en Photo, se creará userId en la tabla photo
  • Si colocas @JoinColumn en User, se creará photoId en la tabla user El lado con @JoinColumn se llama "lado propietario de la relación". El otro lado, sin @JoinColumn, es el "lado inverso (no propietario)".

Funciona igual en relaciones @ManyToMany: usas @JoinTable para indicar el lado propietario.

En relaciones @ManyToOne o @OneToMany, @JoinColumn no es necesario porque estos decoradores son diferentes y la tabla donde colocas @ManyToOne tendrá la columna relacional.

Los decoradores @JoinColumn y @JoinTable también permiten configuraciones adicionales como nombres de columnas de unión o nombres de tablas de unión.

¿Cómo añado columnas adicionales en una tabla de relación muchos-a-muchos?

No es posible añadir columnas extras en tablas creadas por relaciones muchos-a-muchos. Debes crear una entidad separada y vincularla mediante dos relaciones muchos-a-uno con las entidades objetivo (el efecto será equivalente a una tabla muchos-a-muchos), y añadir allí las columnas adicionales. Más detalles en Relaciones Muchos-a-Muchos.

¿Cómo manejar la opción del compilador TypeScript outDir?

Cuando usas la opción del compilador outDir, no olvides copiar los recursos que tu aplicación utiliza en el directorio de salida. De lo contrario, asegúrate de configurar las rutas correctas hacia esos recursos.

Es importante saber que cuando eliminas o mueves entidades, las entidades antiguas permanecen intactas dentro del directorio de salida. Por ejemplo, creas una entidad Post y luego la renombras a Blog, ya no tienes Post.ts en tu proyecto. Sin embargo, Post.js permanece en el directorio de salida. Ahora, cuando TypeORM lee entidades desde tu directorio de salida, encuentra dos entidades: Post y Blog. Esto puede generar errores. Por eso, cuando eliminas o mueves entidades con outDir habilitado, se recomienda encarecidamente eliminar el directorio de salida y recompilar el proyecto nuevamente.

¿Cómo usar TypeORM con ts-node?

Puedes evitar compilar archivos cada vez usando ts-node. Si usas ts-node, puedes especificar entidades ts en las opciones del data source:

{
entities: [__dirname + "/entities/**/*{.js,.ts}"],
subscribers: [__dirname + "/subscribers/**/*{.js,.ts}"]
}

Además, si compilas archivos js en la misma carpeta donde están tus archivos TypeScript, asegúrate de usar la opción del compilador outDir para prevenir este problema.

También, si quieres usar la CLI de ts-node, puedes ejecutar TypeORM de esta forma:

npx typeorm-ts-node-commonjs schema:sync

Para proyectos ESM usa esto en su lugar:

npx typeorm-ts-node-esm schema:sync

¿Cómo usar Webpack para el backend?

Webpack produce advertencias por lo que interpreta como declaraciones require faltantes (para todos los drivers que soporta TypeORM). Para suprimir estas advertencias de drivers no utilizados, debes editar tu archivo de configuración de Webpack.

const FilterWarningsPlugin = require('webpack-filter-warnings-plugin');

module.exports = {
...
plugins: [
// ignore the drivers you don't want. This is the complete list of all drivers -- remove the suppressions for drivers you want to use.
new FilterWarningsPlugin({
exclude: [/mongodb/, /mssql/, /mysql2/, /oracledb/, /pg/, /pg-native/, /pg-query-stream/, /react-native-sqlite-storage/, /redis/, /sqlite3/, /sql.js/, /typeorm-aurora-data-api-driver/]
})
]
};

Agrupar archivos de migraciones

Por defecto, Webpack intenta empaquetar todo en un único archivo. Esto puede ser problemático cuando tu proyecto incluye archivos de migración diseñados para ejecutarse después de desplegar el código empaquetado en producción. Para garantizar que todas tus migraciones sean reconocidas y ejecutadas por TypeORM, es posible que necesites usar la "Sintaxis de Objeto" en la configuración de entry exclusivamente para los archivos de migración.

const { globSync } = require("node:fs")
const path = require("node:path")

module.exports = {
// ... your webpack configurations here...
// Dynamically generate a `{ [name]: sourceFileName }` map for the `entry` option
// change `src/db/migrations` to the relative path to your migrations folder
entry: globSync(path.resolve("src/db/migrations/*.ts")).reduce(
(entries, filename) => {
const migrationName = path.basename(filename, ".ts")
return Object.assign({}, entries, {
[migrationName]: filename,
})
},
{},
),
resolve: {
// assuming all your migration files are written in TypeScript
extensions: [".ts"],
},
output: {
// change `path` to where you want to put transpiled migration files.
path: __dirname + "/dist/db/migrations",
// this is important - we want UMD (Universal Module Definition) for migration files.
libraryTarget: "umd",
filename: "[name].js",
},
}

Además, desde Webpack 4, al usar mode: 'production', los archivos se optimizan por defecto, lo que incluye ofuscar el código para reducir su tamaño. Esto rompe el funcionamiento de las migraciones porque TypeORM depende de sus nombres para determinar cuáles ya se ejecutaron. Puedes desactivar completamente la minimización agregando:

module.exports = {
// ... other Webpack configurations here
optimization: {
minimize: false,
},
}

Alternativamente, si usas UglifyJsPlugin, puedes indicarle que no cambie nombres de clases o funciones así:

const UglifyJsPlugin = require("uglifyjs-webpack-plugin")

module.exports = {
// ... other Webpack configurations here
optimization: {
minimizer: [
new UglifyJsPlugin({
uglifyOptions: {
keep_classnames: true,
keep_fnames: true,
},
}),
],
},
}

Finalmente, asegúrate que en las opciones del data source se incluyan los archivos de migración transpilados:

// TypeORM Configurations
module.exports = {
// ...
migrations: [__dirname + "/migrations/**/*{.js,.ts}"],
}

¿Cómo usar TypeORM en proyectos ESM?

Asegúrate de agregar "type": "module" en el package.json de tu proyecto para que TypeORM sepa usar import( ... ) en los archivos.

Para evitar problemas de dependencias circulares en las importaciones, usa el tipo contenedor Relation en las definiciones de tipos para relaciones en las entidades:

@Entity()
export class User {
@OneToOne(() => Profile, (profile) => profile.user)
profile: Relation<Profile>
}

Esto evita que el tipo de la propiedad se guarde en el código transpilado dentro de los metadatos de la propiedad, previniendo problemas de dependencias circulares.

Dado que el tipo de la columna ya está definido usando el decorador @OneToOne, no se necesita el tipo adicional de metadatos que guarda TypeScript.

Importante: No uses Relation en tipos de columnas que no sean relaciones