如何解决是否可以将键值接口更改为元组
我需要在这两种类型中提供相同的数据
type DataMap = {
id001: 'name1',id002: 'name2',id003: 'name3',....
}
type DataTuple = [
{id: 'id001',name: 'name1'},{id: 'id002',name: 'name2'},{id: 'id003',name: 'name3'},...
]
我只想声明一次这种类型并且有一个单一的事实来源, 但我无法找出将类型从对象转换为元组的实用程序类型函数。
理想情况下,我想做这样的事情:
type DataMap = {
id001: 'name1',....
};
type DataTuple = MapToTuple<DataMap>;
// or
type DataTuple = [
{id: 'id001',...
];
type DataMap = TupletoMap<DataTuple>;
这些函数 MapToTuple<T>
或 TupletoMap<T>
是否可能?
解决方法
对于 TypeScript 4.1+,您可以像这样实现 TupleToMap
,假设您知道 id
属性应该是键,而 name
属性应该是值:
type TupleToMap<T extends { id: PropertyKey,name: any }[]> = {
[V in T[number]as V['id']]: V['name']
};
type DataMap = TupleToMap<DataTuple>;
/* type DataMap = {
id001: "name1";
id002: "name2";
id003: "name3";
} */
上面使用了 TS 4.1 中引入的 key remapping。对于早期版本,您可以这样编写:
type TupleToMap<T extends { id: PropertyKey,name: any }[]> = {
[K in T[number]['id']]: Extract<T[number],{ id: K }>['name']
};
对于 MapToTuple
,不清楚您打算从哪里获得元组的排序。对于人类来说,带有 id001
的条目应该出现在带有 id002
的条目之前可能很明显,但是对于编译器,我不确定是否值得尝试理解它。如果我想出一些不疯狂的东西,我会回过头来。
我有 TupleToMap<T>
的解决方案,虽然它很长
type DataTuple = [
{ id: 'id001'; name: 'name1' },{ id: 'id002'; name: 'name2' },{ id: 'id003'; name: 'name3' }
];
type TupleKeys<T> = Exclude<keyof T,keyof any[]>;
type TupleToObject<T extends Record<string,any>> = {
[k in TupleKeys<T>]: { [P in T[k]['id']]: T[k]['name'] };
}[TupleKeys<T>];
type MergeUnions<T> = (T extends any ? (x: T) => any : never) extends (x: infer R) => any
? { [K in keyof R]: R[K] }
: never;
type TupleToMap<T> = MergeUnions<TupleToObject<T>>;
type DataMap = TupleToMap<DataTuple>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。