我刚刚开始在一个新项目中使用 io-ts 而不是 runtypes。我用于配置验证的模式是使用配置的每个部分的类型创建一个对象;
const configTypeMap = {
jwtSecret: t.string,
environment: t.string,
postgres: postgresConnectionType
} as const
type Config = { [Key in keyof typeof configTypeMap]: t.TypeOf<typeof configTypeMap[Key]> }
以及另一个具有应满足该类型的值的对象;
const envVarMap = {
jwtSecret: process.env.JWT_SECRET,
environment: process.env.ENVIRONMENT,
postgres: {
user: process.env.POSTGRES_USER,
password: process.env.POSTGRES_PASSWORD,
host: process.env.POSTGRES_HOST,
port: process.env.POSTGRES_PORT,
database: process.env.POSTGRES_DATABASE,
}
} as const
然后我创建一个函数,该函数接受一个键并返回该键下经过验证的配置片段;
const getConfig = <T extends keyof Config>(key: T): Config[T] => {
const result: Either<t.Errors, Config[T]> = configTypeMap[key].decode(envVarMap[key])
if (isLeft(result)) {
throw new Error(`Missing config: ${key}`)
}
return result.right
}
这在运行类型中运行良好(尽管看起来有点不同)。但是,在 io-ts 中,configTypeMap[key].decode
推断为;
Left<t.Errors> | Right<string> | Right<{
user: string;
password: string;
host: string;
port: string;
database: string;
}>
它丢失了有关从哪个键访问解码功能的所有上下文。我可以result
转换回正确的类型Either<t.errors, Config[T]>
,但我想要一种方法来做到这一点,而无需转换来验证我不只是忽略错误。
编辑:
在操场上玩耍,我设法得到了一个不涉及 io-ts 的复制示例,所以我认为这只是我对打字稿推理的理解的问题。我仍然想找到一种方法来结束具有签名的函数<T extends keyof Config>(key: T): Config[T]
。