【问题标题】:How to convert array to object in TypeScript?如何在 TypeScript 中将数组转换为对象?
【发布时间】:2021-11-20 05:58:58
【问题描述】:

我正在尝试输入下面的实用函数,它接受一个数组并返回一个对象,如下所示

const convertListToMap = (list, key, secondKey) => {
  const map = {};
  
  for (const ele of list) {
    map[ele[key]] = ele[secondKey]
  }
  
  return map;
}


console.log(convertListToMap([{name: 'isaac', age: 17}, {name: 'john', age: 20}], 'name', 'age'));

console.log(convertListToMap([{race: 'chinese', language: 'mandarin'}, {race: 'malay', language: 'melayu'}], 'race', 'language'));

如您所知,keysecondKey 是动态的,取决于参数list,所以我猜generics 是要走的路。以下是我的尝试

const convertListToMap = <
  T extends object,
  U extends keyof T,
  V extends keyof T
>(
  list: T[],
  key: U,
  secondKey: V
) => {
  const map = {} as Record<U, V>;
  for (const ele of list) {
    map[ele[key]] = ele[secondKey];
  }
  return map;
};

但是,上面给了我错误Type 'T[U]' cannot be used to index type 'Record&lt;U, V&gt;',想知道我做错了哪一部分?

更新

我最近的尝试是更新map的签名如下

  const map = {} as Record<T[U], T[V]>;
  for (const ele of list) {
    map[ele[key]] = ele[secondKey];
  }
  return map;

通过这次最新尝试,对map 变量的赋值很好,但我在记录声明行出现错误,并出现以下错误

类型 'T[U]' 不满足约束 'string |号码 |象征'。 类型 'T[keyof T]' 不可分配给类型 'string |号码 |象征'。 键入'T[字符串] | T[号码] | T[symbol]' 不能分配给类型 'string |号码 |象征'。 类型 'T[string]' 不能分配给类型 'string |号码 |象征'。 类型 'T[string]' 不能分配给类型 'symbol'。 类型 'T[keyof T]' 不能分配给类型 'symbol'。 类型 'T[U]' 不能分配给类型 'symbol'。 类型 'T[keyof T]' 不能分配给类型 'symbol'。 键入'T[字符串] | T[号码] | T[symbol]' 不能分配给类型 'symbol'。 类型 'T[string]' 不可分配给类型 'symbol'.ts(2344)

【问题讨论】:

  • 忽略我(删除评论)。我认为主要问题是您的map 不是Record&lt;U, V&gt; 类型,因为您输入的值来自T,而不是键
  • @Phil:好点,我什至试过const map = {} as Record&lt;T[U], T[V]&gt;;,但它也不起作用哈哈
  • @Phil:我终于找到了解决方案,如果你有兴趣可以看看:D

标签: javascript typescript generics


【解决方案1】:

最后一次尝试的问题是 Record 似乎只期望 string | number | symbol,并且由于 TypeScript 不确定 T[U] 会是什么,因此它抛出了错误。我发现我们可以告诉 TS 更多关于T 的信息如下

const convertListToMap = <
  T extends { [key: string|number]: string | number },
  U extends keyof T,
  V extends keyof T
>(
  list: T[],
  key: U,
  secondKey: V
) => {
  const map = {} as Record<T[U], T[V]>;
  for (const ele of list) {
    map[ele[key]] = ele[secondKey];
  }
  return map;
};

从上面,我们告诉 typescript T 将是 keystring 的对象,并且值将是 string | number 类型,因此,TypeScript 对定义感到满意Record&lt;T[U], T[V]&gt;

这个方案效果很好,TS 可以正确推断

const personObj = convertListToMap([{name: 'isaac', age: 17}, {name: 'john', age: 20}], 'name', 'age')
// const personObj: Record<string, number>

const languageObj = convertListToMap([{race: 'chinese', language: 'mandarin'}, {race: 'malay', language: 'melayu'}], 'race', 'language')
// const languageObj: Record<string,string>

【讨论】:

    猜你喜欢
    • 2021-06-20
    • 2022-09-27
    • 1970-01-01
    • 1970-01-01
    • 2020-06-22
    • 1970-01-01
    • 2020-07-16
    • 2019-05-16
    • 1970-01-01
    相关资源
    最近更新 更多