Typescript中的依赖分离联合



给定一个定义为可能命名配置的常量记录的简单Record<string, Record<string, any>>我想要一个基于键动态限制配置类型的类型。考虑下面的例子:

const configs = {
"fooConfig": {c: "s"},
"barConfig": {c: 1, b: 2}    
} as const;
type ConfigDef<k extends keyof typeof configs = keyof typeof configs> = {
a: k,
v: typeof configs[k]
}
const x: ConfigDef = {
a: "fooConfig",
v: {c: 1, b: 2} // this should not work
}

至关重要的是,对于类型ConfigDef,我需要用户能够隐式地使用该类型,而无需将配置的实际键传递为泛型类型(即他们不应该需要使用显式语法const x: ConfigDef<"fooConfig">)。这可能吗?如果可能,又是如何做到的?

如果您想将ConfigDef引用为特定(非泛型)类型,那么它应该计算为keyof typeof configs中每个K的原始ConfigDeg<K>的并集。也就是说,您需要在联合keyof typeof configs分布ConfigDef<K>。一种方法是编写一个分布式对象类型,如microsoft/TypeScript#47109:

所创造的:
type ConfigDef = { [K in keyof typeof configs]: {
a: K,
v: typeof configs[K]
} }[keyof typeof configs]

结果为

/* type ConfigDef = {
a: "fooConfig";
v: {
readonly c: "s";
};
} | {
a: "barConfig";
v: {
readonly c: 1;
readonly b: 2;
};
} */

,因此给你你想要的行为:

const x: ConfigDef = {
a: "fooConfig",
v: { c: 1, b: 2 } // error!
}

分布式对象类型是指您立即索引到映射类型。一般形式是{[K in KS]: F<K>}[KS],其中KS是一个类似键的类型。在你的情况下,我们把KS改成了keyof typeof configs,把F<K>改成了你原来的ConfigDef<K>

Playground链接到代码

相关内容

  • 没有找到相关文章

最新更新