[英]For a type defined as a map of enum values to strings, how to check with flow that the map object literal has a key for every enum value?
假设我有这种类型
type Status = "draft" | "validated" | "private" | "available" | "archived";
我正在实例化将此枚举类型映射到字符串的对象:
const statusNameMap: { [Status]: string } = {
"draft": "Draft",
"validated": "Validated",
"private": "Private",
"available": "Available",
"archived": "Archived",
};
这工作得很好。 现在的问题是,如何在类型级别检查对象文字必须包含Status
枚举中的所有值作为键?
主要动机是Status
类型实际上不在我的控制范围内,这是通过自省 GraphQL 模式生成的代码,而对象映射用于演示目的。 如果枚举值被添加/删除,我希望 Flow 抱怨我的对象文字没有正确的键。
目前 Flow 可以做到这一点吗?
不 - 至少不是你想要的方式。 据我所知,这不受支持,对我来说压力很大。
但是,您可以使用$ObjMap
来获得您想要的东西。
const MyEnumValues = Object.freeze({
KEY_A: 'VALUE_A',
KEY_B: 'VALUE_B',
KEY_C: 'VALUE_C',
});
const Test8: $Exact<$ObjMap<typeof MyEnumValues, () => string>> = ({
'KEY_A': '',
'KEY_B': '',
//'KEY_C': '', // Errors here!
});
导致在引擎盖下可能看起来像这样的类型:
$Exact<$ObjMap<typeof MyEnumValues, () => string>> = {|
KEY_A: string,
KEY_B: string,
KEY_C: string,
|}
好样的如果您的键和值相同,那么这可能正是您想要的,但它仍然令人沮丧。
这是我运行的测试用例,以获取一个简单的 Enum 设置为 Value set here 。 我还在此处包含了代码,以防 try flow 脱机。
/* @flow */
export const MyEnumValues = Object.freeze({
KEY_A: 'VALUE_A',
KEY_B: 'VALUE_B',
KEY_C: 'VALUE_C',
});
export type MyEnum = $Values<typeof MyEnumValues>;
type ExactMyEnumMap = $Exact<{| +[key: MyEnum]: string |}>;
// NOTE: Needs $Exact bc theres another bug here - only using `|` doesn't work.
// Still doesn't map one-to-one
const Test1: ExactMyEnumMap = {
[MyEnumValues.KEY_A]: '',
// NOTE: Should error...
};
// Exact explicit object literal type
const Test2: ExactMyEnumMap = ({
[MyEnumValues.KEY_A]: '',
// NOTE: Should error...
})
// Explicit object map type.
const Test3: $ObjMap<{| a: 1, b: 2 |}, () => string> = ({
a: '',
b: ''
// NOTE: WORKS -> Except that you have to "redefine" tye type again...
})
// Explicit exact map object literal type. (Ext type)
const Test4: $Exact<$ObjMap<ExactMyEnumMap, () => string>> = ({
[MyEnumValues.KEY_A]: '',
// NOTE: Should error...
})
// Explicit object map object literal type.
const Test5: $ObjMap<{| [MyEnum]: string |}, () => string> = ({
// NOTE: Should error...
})
// Map function type.
const Test6 = (lookup: MyEnum)/* string - same with explicit */ => {
switch (lookup) {
case MyEnumValues.KEY_A:
return '';
case MyEnumValues.KEY_B:
return '';
// NOTE: Should error...
// Typescript reports "not all code paths return a value"
}
}
// Explicit map type.
const Test7: Map<MyEnum, string> = new Map([
// NOTE: Probably shouldn't error but was hoping it would.
]);
// Explicit map type (KEYS ONLY).
const Test8: $Exact<$ObjMap<typeof MyEnumValues, () => string>> = ({
'KEY_A': '',
'KEY_B': '',
//'KEY_C': '', // YES!
});
您可以在这种情况下使用精确类型并使用 {| 定义类型 ... |} 看起来像
const statusNameMap: { [Status]: string } = {|
"draft": "Draft",
"validated": "Validated",
"private": "Private",
"available": "Available",
"archived": "Archived",
|};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.