【问题标题】:configService.get<T>('key') fails on type cast and joi on validationconfigService.get<T>('key') 在类型转换和验证时失败
【发布时间】:2020-04-27 13:56:15
【问题描述】:

我为我的 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。所以我想到了两件事:

  • 我使用泛型类型调用this.configService.get&lt;T&gt;('key'),如图所示here。为什么它仍然返回一个字符串?我希望有一个类型转换。
  • 我使用 joi 进行验证,如 here 所述。我希望 joi 会抛出错误。

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

我错过了什么吗?

【问题讨论】:

  • get() 方法实际上是通用的吗?查看源代码,it's not。即使它是通用的,它也可能实际上是一个字符串,我怀疑实现是否能够执行该转换,通用参数在运行时不可用,也无法对此做任何事情。
  • 感谢您的回复。链接的 NestJsx 存储库不是我认为的官方存储库?那我为什么要提供一个类型=?进一步为什么 Joi 验证成功.. 至少这个应该抛出一个错误...
  • 是的,对不起,我意识到我挖得越多。我找不到那个ConfigService 类的来源。 ¯_(ツ)_/¯
  • 但是,我的评论的第二部分仍然有效,你可以真正告诉编译器返回值应该被视为一个数字,但这并不一定意味着它会是一个数字。
  • 好的found it,它绝对不执行任何转换,它只是获取价值。运行时类型将被读取,这可能是所有字符串。你需要自己转换。

标签: typescript nestjs joi


【解决方案1】:

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

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

你应该这样使用它:

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

ConfigService source
dotenv source

【讨论】:

  • 是的,你是对的。谢谢你的例子。但是为什么 joi 没有抛出错误呢?
  • 我不熟悉nestjs 或joi,所以我不能肯定地告诉你。但如果我冒险猜测,joi 足够聪明,知道数字的字符串表示是有效的。如果您设置的服务器端口不是数字(在进行此转换之前),它可能会失败。
【解决方案2】:

如上所述,这是高度误导的,应该改变。如果泛型指示具体类型,则没有理由显式转换返回值。

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-01
    • 1970-01-01
    • 2014-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-13
    • 1970-01-01
    相关资源
    最近更新 更多