【发布时间】:2022-01-18 07:45:01
【问题描述】:
我正在使用带有类验证器的 nestjs 来验证 env 变量,configuration.service.ts 正在从 configService 文件中获取其值,该文件从 .env 中获取所需的内容并将其放入 json 对象中。
在端口和超时属性中,我希望收到一个字符串,因为它来自 .env 文件,装饰器@Type(() => Number) 将尝试将它收到的任何内容转换为数字。就我而言,装饰器仅在函数调用结束时运行,因此该函数接受一个字符串并返回一个字符串,然后将字符串转换为数字。
问题是属性端口和 connectTimeoutMS 需要一个数字,打字稿 lint 声称它正在接收一个字符串,看起来它没有识别演员表装饰器。 我想知道是否有办法解决这个问题,或者我必须放弃演员阵容。
configuration.service.ts
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Type } from 'class-transformer';
import {
IsBoolean,
IsDefined,
IsInt,
IsNumber,
IsString,
} from 'class-validator';
import { ValidatedConfigService } from 'src/config/utils/validate.config';
import { DatabaseType, Logger } from 'typeorm';
@Injectable()
export class DatabaseConfigService extends ValidatedConfigService {
constructor(private configService: ConfigService) {
super();
}
@IsString()
@IsDefined()
get type(): DatabaseType {
return this.configService.get<DatabaseType>('database.type');
}
@IsString()
@IsDefined()
get host(): string {
return this.configService.get<string>('database.host');
}
@IsInt()
@IsDefined()
@Type(() => Number)
get port(): string {
return this.configService.get<string>('database.port');
}
@IsNumber()
@IsDefined()
@Type(() => Number)
get timeOut(): string {
return (
this.configService.get<string>('database.connectTimeoutMS') ||
'2000'
);
}
@IsString()
@IsDefined()
get entities(): string {
return this.configService.get<string>('database.entities');
}
}
database.configuration.ts
import { Injectable } from '@nestjs/common';
import { ConnectionOptions } from 'typeorm';
import { DatabaseConfigService } from './configuration.service';
export class DatabaseConfigController {
constructor(private readonly configService: DatabaseConfigService) {}
get settings(): ConnectionOptions {
return {
type: this.configService.type,
host: this.configService.host,
port: this.configService.port,
connectTimeoutMS: this.configService.timeOut,
entities: [this.configService.entities],
};
}
}
tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"target": "es2017",
"sourceMap": true,
"outDir": "./dist",
"baseUrl": "./",
"incremental": true,
"skipLibCheck": true,
"strictNullChecks": false,
"noImplicitAny": false,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false
}
}
[编辑 12/20/21]
我不得不放弃使用 @Type() 装饰器,正如 Micael Levi 在他的回答中所说,这行明确告诉 TSC 期待一个字符串 get timeOut(): string。
所以我必须将其更改为数字,但这样做我还需要将我在函数内返回的类型更改为 any 或将其转换为数字。
这种方式会产生明显的类型错误。
@IsInt()
@IsDefined()
get port(): number {
return this.configService.get<string>('db.port');
}
不指定类型不会触发 lint,但在运行时会由于 IsInt() 装饰器而引发错误,因为它从 database.configuration.ts 获取字符串
@IsInt()
@IsDefined()
get port(): number {
return this.configService.get('db.port');
}
解决方法是手动转换成数字,这个转换过程也可以在database.configuration.ts完成。
@IsInt()
@IsDefined()
get port(): number {
return parseInt(this.configService.get<string>('db.port'), 10);
}
也许我使用 @Type() 装饰器的方式并不打算使用它,但我从来不需要使用它,我只是想使用这个包进行所有验证。
【问题讨论】:
标签: typescript nestjs lint class-validator