以类型安全的方式将记录转换为映射-TypeScript



这是我将记录转换为映射的函数:

type MyReturn<Str> = Map<Str, Map<number, number>>;
export const mapRecordToMap = <MyString extends string>(data: Record<MyString, [number, number][]>)
: MyReturn<MyString> => {
const myReturn = new Map<MyString, Map<number, number>>();
Object.entries(data).forEach(([key, value]) => {
myReturn.set(key as MyString, new Map(value as [number, number][]));
});

return myReturn;
};

我的问题是我必须在这里使用'as'

myReturn.set(key as MyString, new Map(value as [number, number][]));

进行正确的类型检查。如何避免这种情况?

谢谢!

您可以使用额外的助手来键入Object.entries:


type Entries<T> = {
[K in keyof T]: [K, T[K]];
}[keyof T][];
const entries = <Obj,>(obj: Obj) => Object.entries(obj) as Entries<Obj>
export const mapRecordToMap = <MyString extends string>(
data: Record<MyString, [number, number][]>) =>
entries(data).reduce((acc, [key, value]) => {
acc.set(key, new Map(value));
return acc
}, new Map<MyString, Map<number, number>>());

游乐场

在这里,您可以找到更多键入Object.entries的方法

附言:如果你使用[].map, [].reduce, {}.keys, {}.entries,并且你想要窄返回类型,你几乎总是需要使用as类型断言。这是最小的邪恶:D

您只需要向Object.entries:添加一个类型参数

type MyReturn<Str> = Map<Str, Map<number, number>>;
export const mapRecordToMap = <MyString extends string>(data: Record<MyString, [number, number][]>)
: MyReturn<MyString> => {
const myReturn = new Map<MyString, Map<number, number>>();
Object.entries<[number, number][]>(data).forEach(([key, value]) => {
myReturn.set(key as MyString, new Map(value));
});

return myReturn;
};

这可能更漂亮,但实际上它与你已经做的没有太大区别。。。实际上,您的类型转换是非常安全的,因为如果类型与参数不匹配,就会产生错误。(不安全铸造的一个迹象是,当你必须做一些更像as unknown as [number, number][]的事情时…(

最新更新