typescript - 从类型中动态排除某个键

标签 typescript typescript-typings typescript-generics

要理解我的问题,首先让我解释一下我想要实现的目标。

我编写了以下groupBy函数:

const groupBy = <T extends Record<keyof T, unknown>>(arr: T[], key: keyof T) => {
    return arr.reduce((prev, { [key]: k, ...rest }) => {
        if (!prev[k]) prev[k] = [] as Omit<T, keyof T>[];
        prev[k].push(rest);

        return prev;
    }, {} as Record<keyof T, Omit<T, keyof T>[]>);
};

现在,假设我有以下界面:

type MyType = {
   city: number,
   name: string
}

以及以下列表:

const L: MyType[] = [
   {
      city: 1,
      name: "name1"
   },
   {
      city: 1,
      name: "name2"
   },
   {
      city: 2,
      name: "name3"
   },
   {
      city: 2,
      name: "name4"
   }
]

当我像这样调用函数时:

const grouped = groupBy(L, "city")

我希望grouped的类型如下:

Record<number, Omit<MyType, "city">[]>
  

即,传递给 groupBy 函数的键应该从数组项的类型中省略。

我怎样才能实现这个目标?这是可以实现的吗?

最佳答案

是的,这是可能的。由于我们需要确保键的类型("city")既是对象的键又是PropertyKey(所以我们可以使用它作为 Record 的键),我认为我们必须使用这样的条件类型:

type GroupByResult<ObjectType, KeyType extends keyof ObjectType> =
    ObjectType[KeyType] extends PropertyKey
    ? Record<ObjectType[KeyType], Omit<ObjectType, KeyType>[]>
    : never;

那么函数的类型是:

export const groupBy = <ObjectType, KeyType extends keyof ObjectType>(
    arr: ObjectType[],
    key: KeyType
): GroupByResult<ObjectType, KeyType> => {
    // ...
};

// ...
const grouped = groupBy(L, "city")
//    ^? −− const grouped: Record<number, Omit<MyType, "city">[]>

Playground link


注意:reduce 调用中存在类型错误。我没有尝试解决这些问题,因为我认为您的问题是关于返回类型的。如果您还需要这些方面的帮助,请告诉我(我怀疑您在实现中总是需要一些类型断言,但我可能是错的)。

但我确实注意到实现中存在一个错误:在索引到 prev 时,您正在使用 key,而您应该使用 kreduce 回调的主体应该是:

if (!prev[k]) prev[k] = [];
prev[k].push(rest);
return prev;

Playground link使用 any 绕过内部类型错误(对于像 groupBy 这样的小型、独立、易于测试的函数来说,这通常足够好)。

关于typescript - 从类型中动态排除某个键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73924450/

相关文章:

html - TypeScript:类型系统的问题

javascript - Typescript 找不到屏幕外 Canvas

javascript - 如何在VIS网络图中添加按选项选择的内容?

typescript - 如何在接口(interface)声明中使用 PromiseConstructorLike 实例的原型(prototype)?

typescript - 如何为通用可选函数参数获得正确的类型推断?

typescript - 订阅从函数返回的 Observable 仅在第一次有效

javascript - 在下面提到的场景中如何为爱好提供 typescript 类型?

visual-studio - visual studio 2017 spa 模板 vue js 丢失

具有枚举泛型类型的 Typescript 对象数组

typescript - 如何一般地键入返回对象数组的值数组的函数?