【问题标题】:Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'键入'字符串 | undefined' 不能分配给类型 'string'。类型“未定义”不可分配给类型“字符串”
【发布时间】:2021-08-19 05:56:43
【问题描述】:

我正在使用 TypeScript 声明以下变量:

const BOT_PREFIX: string = process.env.PREFIX;
const BOT_TOKEN: string = process.env.TOKEN;

我收到以下错误:

键入'字符串 | undefined' 不可分配给类型 'string'。 类型 'undefined' 不可分配给类型 'string'.ts(2322)

我可以通过将数据类型更改为any 来修复它,但我不想这样做。

【问题讨论】:

  • 那么,如果变量未定义怎么办?如果没有为您的进程设置该环境变量,则会发生这种情况。那么BOT_PREFIX 或BOT_TOKEN 应该是什么?

标签: node.js typescript discord.js


【解决方案1】:

由于这些是环境变量,因此可以确保这些值不会为空或未定义。

您可以使用non-null assertion operator

应该是这样的:

const BOT_PREFIX: string = process.env.PREFIX!;
const BOT_TOKEN: string = process.env.TOKEN!;

只需确保您的环境变量已填写。

你也可以这样做:

const BOT_PREFIX: string = process.env.PREFIX || '';
const BOT_TOKEN: string = process.env.TOKEN || '';

【讨论】:

    【解决方案2】:

    节点的process.env 具有以下类型定义(来自this declaration file,它使用定义为here 的类型):

    interface ProcessEnv {
        [key: string]: string | undefined
    }
    

    因此,就 TypeScript 的编译器而言,您在 process.env 下访问的任何属性都将是 string | undefined 类型。那是union,这意味着process.env.RANDOMKEY(例如)要么是string,要么是undefined。一般来说,这是正确的类型;编译器不知道实际设置了哪些环境变量。

    所以这是一个问题:

    const BOT_PREFIX: string = process.env.PREFIX // error!
    

    并且编译器会警告您process.env.PREFIX 可能是undefined,因此将其视为string 是不安全的。

    处理这个问题的方法取决于您是想要方便还是类型安全,以及如果您对 process.env.PREFIX 和 process.env.TOKEN 的假设不正确,您希望看到什么。


    纯粹为了方便,你可能无法击败non-null assertion operator (!):

    const BOT_PREFIX: string = process.env.PREFIX!; // okay
    const BOT_TOKEN: string = process.env.TOKEN!; // okay
    

    在这里,您只是告诉编译器,即使它无法验证这一点,您也可以确定 process.env.PREFIX 和 process.env.TOKEN 将被定义。这实际上只是抑制了编译器警告;它在运行时仍然与您的原始代码做同样的事情。这意味着如果您的断言被证明是错误的,那么您可能会在运行时遇到编译器无法帮助您解决的问题:

    BOT_PREFIX.toUpperCase(); // runtime error if BOT_PREFIX is undefined after all
    

    所以要小心。


    另一方面,您可以尝试通过处理未设置您期望的环境变量的情况来使代码更安全。例如:

    function getEnvVar(v: string): string {
        const ret = process.env[v];
        if (ret === undefined) {
            throw new Error("process.env." + v + " is undefined!");
        }
        return ret;
    }
    
    const BOT_PREFIX: string = getEnvVar("PREFIX");
    const BOT_TOKEN: string = getEnvVar("TOKEN");
    

    这里我们编写了一个名为getEnvVar() 的函数,它获取环境变量的名称并返回其值,只要该值是string。如果未定义环境变量,则会引发运行时错误。 TypeScript 通过control flow analysis 了解getEnvVar() 的返回类型是string(而不是string | undefined;undefined 的可能性已被throw 语句消除),因此您可以安全地分配返回值到string 类型的变量。

    此代码显然不太方便,因为它需要额外的运行时代码,但现在与其可能对编译器撒谎并产生奇怪的运行时行为,如果您的假设无效,您将在运行时立即获得一些反馈。


    Playground link to code

    【讨论】:

    • typeof ret === "undefined" 不会像 ret === undefined 一样清晰吗?
    • 也许吧?我猜想可以重新分配名为undefined 的变量的日子是long gone,但出于某种原因,我总是写typeof x === "undefined" 是为了“安全”。我会改的
    • 真的非常感谢!!
    猜你喜欢
    • 2021-04-06
    • 2021-06-12
    • 1970-01-01
    • 1970-01-01
    • 2022-01-07
    • 2019-04-10
    • 2019-03-28
    • 2021-09-14
    • 1970-01-01
    相关资源
    最近更新 更多