使用数组元素中公共属性的键将数组转换为对象

我有一个与此相似的对象:

const v = [
  { pointer: "/name",name: "N1" },{ pointer: "/name",name: "N2" },{ pointer: "/zip",name: "Z1" }
] as const

我想生成这样的对象:

const m: M = {
  "/name": [{ pointer: "/name",name: "N2" }] // can also contain N1,but not Z1
}

是否可以为此创建类型?我的尝试应该更好地解释我要做什么:

type V = typeof v;
type T = V[number]

type M = {
  [K in T["pointer"]]: Array<T extends {pointer: K} ? T : never>;
}

codesandbox:https://codesandbox.io/s/56564

iCMS 回答:使用数组元素中公共属性的键将数组转换为对象

您已经接近了,但是问题在于您的T是具体类型而不是泛型类型参数,因此T extends { pointer: K } ? T : never不是distributive over unions。因此,T extends { pointer: K }对于每个K的选择都是错误的,您得到never[]而不是您想要的内容。

获取分布条件类型的最简单方法是使用格式为type Something<X> = X extends { pointer: K } ? X : never的类型别名,然后插入Something<T>。幸运的是,内置Extract<T,U> utility type已通过这种方式工作。所以我们可以这样写:

type M = { [K in T["pointer"]]?: Array<Extract<T,{ pointer: K }>> };

计算结果为:

/* 
type M = {
    "/name"?: ({
        readonly pointer: "/name";
        readonly name: "N1";
    } | {
        readonly pointer: "/name";
        readonly name: "N2";
    })[];
    "/zip"?: {
        readonly pointer: "/zip";
        readonly name: "Z1";
    }[];
}
*/

我认为,哪个更接近您想要的。请注意,由于您的m常量没有所有的道具,因此我将道具设为可选:

const m: M = {
    "/name": [{ pointer: "/name",name: "N2" }]
}; // okay

好的,希望能有所帮助;祝你好运!

Playground link to code

本文链接:https://www.f2er.com/2089457.html

大家都在问