打字稿中的相关不相交联合
Dependent Disjoint Unions in 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
引用为特定 (non-generic) 类型,则它的计算结果应为 union of your original ConfigDeg<K>
for each K
in keyof typeof configs
. That is, you need to distribute ConfigDef<K>
across the union keyof typeof configs
. One way to do this is to write a distributive object type as coined in 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!
}
分布式对象类型是当你立即index into a mapped type。一般形式是{[K in KS]: F<K>}[KS]
,其中KS
是keylike类型。在您的情况下,我们将 KS
设为 keyof typeof configs
,将 F<K>
作为您的原始 ConfigDef<K>
。
给定一个简单的 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
引用为特定 (non-generic) 类型,则它的计算结果应为 union of your original ConfigDeg<K>
for each K
in keyof typeof configs
. That is, you need to distribute ConfigDef<K>
across the union keyof typeof configs
. One way to do this is to write a distributive object type as coined in 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!
}
分布式对象类型是当你立即index into a mapped type。一般形式是{[K in KS]: F<K>}[KS]
,其中KS
是keylike类型。在您的情况下,我们将 KS
设为 keyof typeof configs
,将 F<K>
作为您的原始 ConfigDef<K>
。