在lodash中,_.invert
函数反转对象的键和值:
var object = { 'a': 'x', 'b': 'y', 'c': 'z' };
_.invert(object);
// => { 'x': 'a', 'y': 'b', 'z': 'c' }
lodash类型当前声明它总是返回string
→ string
Map:
_.invert(object); // type is _.Dictionary<string>
但有时候,特别是当你使用constAssert时,更精确的类型会更合适:
const o = {
a: 'x',
b: 'y',
} as const; // type is { readonly a: "x"; readonly b: "y"; }
_.invert(o); // type is _.Dictionary<string>
// but would ideally be { readonly x: "a", readonly y: "b" }
打字能打得这么精确吗?这个声明接近:
declare function invert<
K extends string | number | symbol,
V extends string | number | symbol,
>(obj: Record<K, V>): {[k in V]: K};
invert(o); // type is { x: "a" | "b"; y: "a" | "b"; }
键是正确的,但值是输入键的并集,i。即,你失去了Map的特异性。有可能做到完美吗?
3条答案
按热度按时间6tqwzwtp1#
编辑
由于在Map类型中引入了
as
子句,因此可以将此类型写成:您可以使用带有as子句的Map类型:
Playground链接
原始答案
你可以使用一个更复杂的Map类型来实现,它可以保留正确的值:
Playground链接
AllValues
首先创建一个包含所有key
、value
对的并集(因此对于示例,这将是{ key: "a"; value: "x"; } | { key: "b"; value: "y"; }
)。在Map的类型中,我们Map联合中的所有value
类型,对于每个value
,我们使用Extract
提取原始key
。只要没有重复的值,这将工作得很好(如果有重复的值,我们将得到一个键的并集,在这里值出现)a1o7rhls2#
Titian Cernicova-Dragomir的解决方案非常酷。今天,我发现了另一种用条件类型交换对象键和值的方法:
使用
const o
测试:声明
invert
函数的方式与上面的答案相同,返回类型为Invert<T>
。Playground
fjnneemd3#
这在TypeScript 4中变得非常简单。1对Map类型中的键重Map的支持:
Playground