[英]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.