我有这个keyBy功能:

export function keyBy<T>(items: T[] | undefined, extractId: (item: T) => number): Record<number, T> {
  const obj: Record<number, T> = {};

  if (items) {
    items.forEach(item => {
      const id = extractId(item);
      obj[id] = item;
    });
  }

  return obj;
}

它可以用于将对象数组转换为这些对象的字典,以您想要的任何内容为关键字.例如:

const users = [user1, user2, ...]l
const usersById = keyBy(users, u => u.id);

现在我想更改此函数,使其不仅可以使用ID之类的数字键,还可以使用字符串:

export function keyBy<Key extends string | number, T>(items: T[] | undefined, extractId: (item: T) => Key): Record<Key, T> {
  const obj: Record<Key, T> = {};

  if (items) {
    items.forEach(item => {
      const id = extractId(item);
      obj[id] = item;
    });
  }

  return obj;
}

这会产生错误Type '{}' is not assignable to type 'Record<Key, T>'. ts(2322).为什么这不管用?

我认为问题是现在每id个可以是一个字符串或一个数字,而我想要的是所有的ID要么是一个字符串要么是一个数字,但当然它们都是同一类型的.

推荐答案

不能将空对象分配给具有可枚举键的Record:

Note: I am not sure it is called "enumerable".
However, in this post, "enumerable" means all value are known like "a" | "b" or 1 | 2 | 3, and string or number is not "enumerable"

const obj1: Record<"id", number> = {}
// Property 'id' is missing in type '{}' but required in type 'Record<"id", number>'.

const obj2: Record<string, number> = {}
// OK

在您的keyBy函数中,可以将Eventable传递到Key泛型参数中,这会导致空对象赋值问题.

最简单的方法就是使用as关键字将其转换为您想要的内容:

const obj = {} as Record<Key, T>;

Typescript相关问答推荐

类型保护,用于验证是否定义了二元组的每个项

输入具有相同键但值类型不同的对象

我用相同的Redux—Toolkit查询同时呈现两个不同的组件,但使用不同的参数

类型脚本强制泛型类型安全

异步动态生成Playwright测试,显示未找到测试

在数据加载后,如何使用NgFor在使用异步管道的可观测对象上生成子组件?

如何使所有可选字段在打印脚本中都是必填字段,但不能多或少?

寻址对象中路径的泛型类型

将带点的对象键重新映射为具有保留值类型的嵌套对象

在Cypress中,是否可以在不标识错误的情况下对元素调用.Click()方法?

如何创建由空格连接的多个字符串的类型

如果判断空值,则基本类型Gaurd不起作用

是否将Angular *ngFor和*ngIf迁移到新的v17语法?

我可以将一个类型数组映射到TypeScrip中的另一个类型数组吗?

仅当类型为联合类型时映射属性类型

T的typeof键的Typescript定义

Typescript:是否将联合类型传递给重载函数?

如何使用 Angular 确定给定值是否与应用程序中特定单选按钮的值匹配?

如何通过nx找到所有受影响的项目?

我是否应该在 Next.js 中的服务器组件中获取秘密数据的所有函数中使用使用服务器?