从 Object.assign 返回和从 Typescript 中的自定义对象返回有什么不同
What's different between returning from Object.assign and from customized object in Typescript
我在 NestJS 中使用 typeorm,在 app.module.ts
我尝试通过申请 forRootAsync
来初始化我的数据库设置
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (configService: ConfigService) => ({
type: configService.get('database.type'),
host: configService.get('database.host'),
port: configService.get('database.port'),
username: configService.get('database.username'),
password: configService.get('database.password'),
database: configService.get('database.database'),
entities: configService.get('database.entities'),
synchronize: configService.get('database.synchronize'),
logging: configService.get('database.logging'),
}),
}),
在编译过程中出现以下错误:
error TS2322: Type '(configService: ConfigService) => Promise<{ type: "mysql" | "mariadb" | "postgres" | "cockroachdb" | "sqlite" | "mssql" | "sap" | "oracle" | "cordova" | "nativescript" | "react-native" | "sqljs" | "mongodb" | "aurora-data-api" | "aurora-data-api-pg" | "expo" | "better-sqlite3"; ... 7 more ...; logging: LoggerOptions...' is not assignable to type '(...args: any[]) => TypeOrmModuleOptions | Promise<TypeOrmModuleOptions>'.
Type 'Promise<{ type: "mysql" | "mariadb" | "postgres" | "cockroachdb" | "sqlite" | "mssql" | "sap" | "oracle" | "cordova" | "nativescript" | "react-native" | "sqljs" | "mongodb" | "aurora-data-api" | "aurora-data-api-pg" | "expo" | "better-sqlite3"; ... 7 more ...; logging: LoggerOptions; }>' is not assignable to type 'TypeOrmModuleOptions | Promise<TypeOrmModuleOptions>'.
Type 'Promise<{ type: "mysql" | "mariadb" | "postgres" | "cockroachdb" | "sqlite" | "mssql" | "sap" | "oracle" | "cordova" | "nativescript" | "react-native" | "sqljs" | "mongodb" | "aurora-data-api" | "aurora-data-api-pg" | "expo" | "better-sqlite3"; ... 7 more ...; logging: LoggerOptions; }>' is not assignable to type 'Promise<TypeOrmModuleOptions>'.
Type '{ type: "mysql" | "mariadb" | "postgres" | "cockroachdb" | "sqlite" | "mssql" | "sap" | "oracle" | "cordova" | "nativescript" | "react-native" | "sqljs" | "mongodb" | "aurora-data-api" | "aurora-data-api-pg" | "expo" | "better-sqlite3"; ... 7 more ...; logging: LoggerOptions; }' is not assignable to type 'TypeOrmModuleOptions'.
Type '{ type: "mysql" | "mariadb" | "postgres" | "cockroachdb" | "sqlite" | "mssql" | "sap" | "oracle" | "cordova" | "nativescript" | "react-native" | "sqljs" | "mongodb" | "aurora-data-api" | "aurora-data-api-pg" | "expo" | "better-sqlite3"; ... 7 more ...; logging: LoggerOptions; }' is not assignable to type '{ retryAttempts?: number; retryDelay?: number; toRetry?: (err: any) => boolean; autoLoadEntities?: boolean; keepConnectionAlive?: boolean; verboseRetryLog?: boolean; } & Partial<AuroraDataApiConnectionOptions>'.
Type '{ type: "mysql" | "mariadb" | "postgres" | "cockroachdb" | "sqlite" | "mssql" | "sap" | "oracle" | "cordova" | "nativescript" | "react-native" | "sqljs" | "mongodb" | "aurora-data-api" | "aurora-data-api-pg" | "expo" | "better-sqlite3"; ... 7 more ...; logging: LoggerOptions; }' is not assignable to type 'Partial<AuroraDataApiConnectionOptions>'.
Types of property 'type' are incompatible.
Type '"mysql" | "mariadb" | "postgres" | "cockroachdb" | "sqlite" | "mssql" | "sap" | "oracle" | "cordova" | "nativescript" | "react-native" | "sqljs" | "mongodb" | "aurora-data-api" | "aurora-data-api-pg" | "expo" | "better-sqlite3"' is not assignable to type '"aurora-data-api"'.
Type '"mysql"' is not assignable to type '"aurora-data-api"'.
19 useFactory: async (configService: ConfigService) => ({
~~~~~~~~~~
node_modules/@nestjs/typeorm/dist/interfaces/typeorm-options.interface.d.ts:19:5
19 useFactory?: (...args: any[]) => Promise<TypeOrmModuleOptions> | TypeOrmModuleOptions;
~~~~~~~~~~
The expected type comes from property 'useFactory' which is declared here on type 'TypeOrmModuleAsyncOptions'
但是如果我在返回之前应用 Object.assign() 它将通过
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (configService: ConfigService) =>
Object.assign({
type: configService.get('database.type'),
host: configService.get('database.host'),
port: configService.get('database.port'),
username: configService.get('database.username'),
password: configService.get('database.password'),
database: configService.get('database.database'),
entities: configService.get('database.entities'),
synchronize: configService.get('database.synchronize'),
logging: configService.get('database.logging'),
}),
}),
这是因为 Object.assign() 将对象转换为 any 类型吗?
异步初始化 typeorm 的常用方法是什么?
正如我从您的日志中看到的那样 - Type '"mysql"' is not assignable to type '"aurora-data-api"'.
您可以参考- Overriding options defined in ormconfig。 Here它明确提到了附加自定义命名策略或自定义记录器的示例。
TypeORM 提供了 getConnectionOptions
函数,可以从 ormconfig 文件或环境变量中读取连接选项。 - Hint mentioned on TypeORM Integration
搜索后我找到了这个帖子。
https://github.com/nestjs/nest/issues/1119
它说我们需要具体分配类型。
所以我更改了 return 对象中的类型 属性:
type: configService.get('database.type') as 'mysql',
但是如果我删除 Object.assign(),我仍然会遇到同样的编译错误,我注意到行
password: configService.get('database.password')
将 configService.get() 转换为
的值
string | (() => string) | (() => Promise<string>);
这导致了问题,所以我需要传递类型,最终配置如下所示:
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (configService: ConfigService) => ({
type: configService.get('database.type') as 'mysql',
host: configService.get('database.host'),
port: configService.get('database.port'),
username: configService.get('database.username'),
password: configService.get('database.password'),
database: configService.get<string>('database.database'),
entities: [configService.get('database.entities')],
synchronize: configService.get<boolean>('database.synchronize'),
logging: configService.get<boolean>('database.logging'),
}),
})
但我仍然不知道为什么它会将密码强制转换为那种奇怪的类型。
我在 NestJS 中使用 typeorm,在 app.module.ts 我尝试通过申请 forRootAsync
来初始化我的数据库设置TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (configService: ConfigService) => ({
type: configService.get('database.type'),
host: configService.get('database.host'),
port: configService.get('database.port'),
username: configService.get('database.username'),
password: configService.get('database.password'),
database: configService.get('database.database'),
entities: configService.get('database.entities'),
synchronize: configService.get('database.synchronize'),
logging: configService.get('database.logging'),
}),
}),
在编译过程中出现以下错误:
error TS2322: Type '(configService: ConfigService) => Promise<{ type: "mysql" | "mariadb" | "postgres" | "cockroachdb" | "sqlite" | "mssql" | "sap" | "oracle" | "cordova" | "nativescript" | "react-native" | "sqljs" | "mongodb" | "aurora-data-api" | "aurora-data-api-pg" | "expo" | "better-sqlite3"; ... 7 more ...; logging: LoggerOptions...' is not assignable to type '(...args: any[]) => TypeOrmModuleOptions | Promise<TypeOrmModuleOptions>'.
Type 'Promise<{ type: "mysql" | "mariadb" | "postgres" | "cockroachdb" | "sqlite" | "mssql" | "sap" | "oracle" | "cordova" | "nativescript" | "react-native" | "sqljs" | "mongodb" | "aurora-data-api" | "aurora-data-api-pg" | "expo" | "better-sqlite3"; ... 7 more ...; logging: LoggerOptions; }>' is not assignable to type 'TypeOrmModuleOptions | Promise<TypeOrmModuleOptions>'.
Type 'Promise<{ type: "mysql" | "mariadb" | "postgres" | "cockroachdb" | "sqlite" | "mssql" | "sap" | "oracle" | "cordova" | "nativescript" | "react-native" | "sqljs" | "mongodb" | "aurora-data-api" | "aurora-data-api-pg" | "expo" | "better-sqlite3"; ... 7 more ...; logging: LoggerOptions; }>' is not assignable to type 'Promise<TypeOrmModuleOptions>'.
Type '{ type: "mysql" | "mariadb" | "postgres" | "cockroachdb" | "sqlite" | "mssql" | "sap" | "oracle" | "cordova" | "nativescript" | "react-native" | "sqljs" | "mongodb" | "aurora-data-api" | "aurora-data-api-pg" | "expo" | "better-sqlite3"; ... 7 more ...; logging: LoggerOptions; }' is not assignable to type 'TypeOrmModuleOptions'.
Type '{ type: "mysql" | "mariadb" | "postgres" | "cockroachdb" | "sqlite" | "mssql" | "sap" | "oracle" | "cordova" | "nativescript" | "react-native" | "sqljs" | "mongodb" | "aurora-data-api" | "aurora-data-api-pg" | "expo" | "better-sqlite3"; ... 7 more ...; logging: LoggerOptions; }' is not assignable to type '{ retryAttempts?: number; retryDelay?: number; toRetry?: (err: any) => boolean; autoLoadEntities?: boolean; keepConnectionAlive?: boolean; verboseRetryLog?: boolean; } & Partial<AuroraDataApiConnectionOptions>'.
Type '{ type: "mysql" | "mariadb" | "postgres" | "cockroachdb" | "sqlite" | "mssql" | "sap" | "oracle" | "cordova" | "nativescript" | "react-native" | "sqljs" | "mongodb" | "aurora-data-api" | "aurora-data-api-pg" | "expo" | "better-sqlite3"; ... 7 more ...; logging: LoggerOptions; }' is not assignable to type 'Partial<AuroraDataApiConnectionOptions>'.
Types of property 'type' are incompatible.
Type '"mysql" | "mariadb" | "postgres" | "cockroachdb" | "sqlite" | "mssql" | "sap" | "oracle" | "cordova" | "nativescript" | "react-native" | "sqljs" | "mongodb" | "aurora-data-api" | "aurora-data-api-pg" | "expo" | "better-sqlite3"' is not assignable to type '"aurora-data-api"'.
Type '"mysql"' is not assignable to type '"aurora-data-api"'.
19 useFactory: async (configService: ConfigService) => ({
~~~~~~~~~~
node_modules/@nestjs/typeorm/dist/interfaces/typeorm-options.interface.d.ts:19:5
19 useFactory?: (...args: any[]) => Promise<TypeOrmModuleOptions> | TypeOrmModuleOptions;
~~~~~~~~~~
The expected type comes from property 'useFactory' which is declared here on type 'TypeOrmModuleAsyncOptions'
但是如果我在返回之前应用 Object.assign() 它将通过
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (configService: ConfigService) =>
Object.assign({
type: configService.get('database.type'),
host: configService.get('database.host'),
port: configService.get('database.port'),
username: configService.get('database.username'),
password: configService.get('database.password'),
database: configService.get('database.database'),
entities: configService.get('database.entities'),
synchronize: configService.get('database.synchronize'),
logging: configService.get('database.logging'),
}),
}),
这是因为 Object.assign() 将对象转换为 any 类型吗? 异步初始化 typeorm 的常用方法是什么?
正如我从您的日志中看到的那样 - Type '"mysql"' is not assignable to type '"aurora-data-api"'.
您可以参考- Overriding options defined in ormconfig。 Here它明确提到了附加自定义命名策略或自定义记录器的示例。
TypeORM 提供了 getConnectionOptions
函数,可以从 ormconfig 文件或环境变量中读取连接选项。 - Hint mentioned on TypeORM Integration
搜索后我找到了这个帖子。
https://github.com/nestjs/nest/issues/1119
它说我们需要具体分配类型。
所以我更改了 return 对象中的类型 属性:
type: configService.get('database.type') as 'mysql',
但是如果我删除 Object.assign(),我仍然会遇到同样的编译错误,我注意到行
password: configService.get('database.password')
将 configService.get() 转换为
的值string | (() => string) | (() => Promise<string>);
这导致了问题,所以我需要传递类型,最终配置如下所示:
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (configService: ConfigService) => ({
type: configService.get('database.type') as 'mysql',
host: configService.get('database.host'),
port: configService.get('database.port'),
username: configService.get('database.username'),
password: configService.get('database.password'),
database: configService.get<string>('database.database'),
entities: [configService.get('database.entities')],
synchronize: configService.get<boolean>('database.synchronize'),
logging: configService.get<boolean>('database.logging'),
}),
})
但我仍然不知道为什么它会将密码强制转换为那种奇怪的类型。