configService.get<T>('key') 类型转换和 joi 验证失败

configService.get<T>('key') fails on type cast and joi on validation

我为我的 NestJs REST 创建了一个自定义配置文件 API。这是应用程序正在侦听的端口的简单示例。

我有一个包含以下内容的 .env 文件

SERVER_PORT = 3000

我的配置文件示例

import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as Joi from '@hapi/joi';

@Injectable()
export class ServerConfigService {
  constructor(private readonly configService: ConfigService) {
    const { error } = Joi.object({
      port: Joi.number()
        .port()
        .required(),
    }).validate({ port: this.port });

    if (error) { // no error thrown
      throw error;
    }

    console.log(typeof this.port); // type is string but should be number
  }

  public get port(): number {
    return this.configService.get<number>('SERVER_PORT');
  }
}

我希望端口类型为 number,但它仍然是 string。所以我想到两件事:

端口变量可能是一个不好的例子,因为 Nest 能够处理字符串类型的端口。但是如果配置变量应该是数字但属于字符串类型,则其他部分需要数字并抛出错误。

我是不是漏掉了什么?

您使用 ConfigService 找到的示例非常具有误导性。误导的是泛型类型参数。您传递给它的类型只会影响 return 值的处理方式。实际运行时类型将是读取时的类型。

NestJs 使用 dotenv 读取配置文件,所有值都被简单地读取为字符串。未进行任何转换。

你应该这样使用它:

public get port(): number {
  return +this.configService.get('SERVER_PORT');
}

ConfigService source
dotenv source

如上所写,这是极具误导性的,应予以更改。如果泛型指示具体类型,则没有理由显式转换返回值。

我不明白的是为什么没有类型转换异常:

const myNumber:number = this.configService.get('PROPERTY_PATH');

即使 ConfigService 有效地 returns 一个字符串,如何将它按原样分配给一个数字?事实上,myNumber 实际上是一个字符串,即使它被明确定义为数字。这同样是一个 Typescript 问题。