输入'字符串undefined'不能分配给类型'string'。“未定义”类型不能分配给“字符串”类型
我正在使用 TypeScript 声明以下变量:
const BOT_PREFIX: string = process.env.PREFIX;
const BOT_TOKEN: string = process.env.TOKEN;
我收到以下错误:
输入'字符串| undefined' 不能分配给类型 'string'。类型 'undefined' 不可分配给类型 'string'.ts(2322)
我可以通过将数据类型更改为 来修复它any,但我不想这样做。
回答
Nodeprocess.env具有以下类型定义(来自使用此处定义的类型的声明文件):
interface ProcessEnv {
[key: string]: string | undefined
}
因此,就 TypeScript 的编译器而言,您在其下访问的任何属性都process.env将是类型string | undefined。那是一个union,这意味着process.env.RANDOMKEY(例如)要么是 astring要么就是undefined。一般来说,这是正确的类型;编译器不知道实际设置了哪些环境变量。
所以这是一个问题:
const BOT_PREFIX: string = process.env.PREFIX // error!
并且编译器警告您process.env.PREFIX可能是undefined,因此将其视为string.
为了解决这个问题的方式取决于你是否要方便或类型安全,你想要什么,看看你对发生的假设process.env.PREFIX和process.env.TOKEN不正确。
为了纯粹的方便,您可能无法击败非空断言运算符 ( !):
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(),它接受环境变量的名称并返回它的值,只要该值是 a string。如果未定义环境变量,则会抛出运行时错误。TypeScript 通过控制流分析了解到 的返回类型getEnvVar()是string(而不是string | undefined;语句undefined已经消除了可能性throw),因此您可以安全地将返回值分配给类型为 的变量string。
这段代码显然不太方便,因为它需要额外的运行时代码,但是现在,如果您的假设无效,您将在运行时立即获得一些反馈,而不是可能对编译器撒谎并具有奇怪的运行时行为。
Playground 链接到代码