如何使类型安全的环境变量加载器



我想做一个动态的。env加载器和验证器。我使用的是envalid包,然后是一个自定义函数,该函数根据参数输入加载环境变量。

我有一个类的属性requiredEnvs = [{ name: 'DATABASE_URL', type: str() }],然后我调用我的loadEnv函数const env = loadEnv(requiredEnvs)。现在我应该能够访问env.DATABASE_URL上的DATABASE_URL,也有智能感知。

这是我的loadEnv函数

const loadEnv = (envRequirements: EnvironmentVariable[])=> {
const obj = envRequirements.reduce((result, curr) => {
result[curr.name]  = curr.type
return result; 
}, {})
const env = cleanEnv(process.env, obj)
return env
}

然而,在loadEnv函数中,我得到一个错误说"元素隐式地具有'any'类型,因为类型'any'的表达式不能用于索引类型'{}'"我认为这是我的问题的主要根源。

我试过设置curr.name作为这么多类型,但我不知道。我想我必须使用typescript动态键入功能,但我还没有经验,所以我真的需要一些帮助,谢谢。

下面是复制这个问题的repo: https://github.com/davidprokopec/typescript-loadEnvProblem

这里应该有一个操场

Array.prototype.reduce()具有通用签名。当您不为类型参数提供任何参数时,它会从最后的initialValue参数推断出您试图创建的对象的类型,该参数当前为{}

由于从值{}推断类型得到的是{}的类型,即"一个从未有任何键或值的对象",因此typescript会产生错误,因为您试图将值赋给不应该存在的键。

解决这个问题的方法是为reduce提供一个合适的泛型类型参数。

const obj = envRequirements.reduce<Record<string, string>>((result, curr) => {
result[curr.name] = curr.type;
return result;
}, {});

我在这里选择了Record<string, string>,因为我不知道你想给这个值分配什么类型。你可以通过执行Record<string, EnvironmentVariable['type']>

从"环境变量"中获取它