尝试使用Map来实现字典
但是,尽管输入所有可能的键并使用 ReadonlyMap Map.get(key) 返回 valueType |欠定义
type dictKeys = 'key1' | 'key2' | 'key3'
const dictObj:ReadonlyMap<DictKeys, string> = new Map<DictKeys, string>{
key1: 'value1',
key2: 'value2',
key3: 'value3',
} satisfies Record<dictKeys, string>
function testDictObj(key: dictKeys) {
const res = dictObj[key]
return res
}
const dictMap:ReadonlyMap<DictKeys, string> = new Map([
['key1', 'value1'],
['key2', 'value2'],
['key3', 'value3'],
])
function testDictMap(key: dictKeys) {
const res = dictMap.get(key)
return res
}
恕我直言,TS 应该知道缩小范围所需的所有类型,以及如果映射中存在无效键的类型或缺少道具键定义 - 它会发出警告,因此
const res = dictMap.get(key)
应该只给出“字符串”类型
如果使用对象 - 一切都很好,但对于字典来说,使用映射更语义 是的,我可以使用断言“!”因为我对结果很确定,但它似乎不太整洁(
也许已经有walkaroung或自定义实用程序类型了?
虽然 TypeScript 可以对
object
类型进行类型推断,但它必须遵循 Map 类已定义的类型定义。 Map
和 ReadonlyMap
都定义了 get
方法,如下所示:
get(key: K): V | undefined;
所以 TypeScript 无法自动知道该值不能是
undefined
。
您可以像这样扩展
Map
类:
class StrictMap<K, V> extends Map<K, V> {
public override get(key: K): V {
const result = super.get(key);
if (result === undefined) {
throw Error("Key not found");
}
return result;
}
}
通过使用此实现,get 方法永远不会返回
undefined
,而是抛出异常。
如果您需要将其转换为只读,您也可以扩展此接口:
interface ReadonlyStrictMap<K, V> extends ReadonlyMap<K, V> {
get(key: K): V;
}
现在您的示例可以运行并且
get
返回 string
:
const dictMap = new StrictMap([
['key1', 'value1'],
['key2', 'value2'],
['key3', 'value3'],
]) satisfies ReadonlyStrictMap<dictKeys, string>;
function testDictMap(key: dictKeys) {
const res = dictMap.get(key)
return res // <-- Type: string
}
(编辑:示例中的
satisfies
并不是真正需要的,只需使其接近您自己的示例即可。)