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

Transforming an array to an object with key from common property in elements of array

我有一个类似这样的对象:

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

你很接近,但问题是你的 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