打字稿不推断通用对象的值

Posted

技术标签:

【中文标题】打字稿不推断通用对象的值【英文标题】:Typescript doesn't infer value of generic object 【发布时间】:2020-08-27 11:49:48 【问题描述】:

考虑一下这个函数,它遍历提供的对象的键并将每个键设置为一个数字,然后返回该对象。出于某种原因,打字稿没有推断出 obj[key] 值是一个数字,我收到以下错误:

类型 '1' 不可分配给类型 'T[keyof T]'.ts(2322)

有谁知道如何解决这个问题?参数应始终为Record<string, number>

function setObjKeysToOne<T extends Record<string, number>>(obj: T) 
  (Object.keys(obj) as Array<keyof typeof obj>).forEach((key) => 
    obj[key] = 1; // Type '1' is not assignable to type 'T[keyof T]'.ts(2322)
  );

  return obj;

【问题讨论】:

你确定你需要它通用吗? Playground 是的,我确实需要它,这不是真实世界的代码,我创建它是为了说明问题,实际上我需要一个泛型。 如果没有更多的用例,我会警惕这种代码。该签名不需要是通用的,如果TRecord&lt;string, number&gt; 窄,例如a: 123, b: 456 属性为numeric literal types,那么您想要编译器抱怨设置其属性为1 @jcalz 我在这里看到了问题,但我只想确保值是数字,我不在乎它们是否是文字。我想类型转换是这里唯一的方法。在实际代码中,当满足某个条件时,我将值设置为0,如果这更有意义的话,这是一个人为的例子。 【参考方案1】:

您可以在分配期间强制转换 obj,例如

function setObjKeysToOne<T extends Record<string, number>>(obj: T) 
  Object.keys(obj).forEach((key) => 
    (obj as Record<string, number>)[key] = 1;
  );

  return obj;

在 github 上有一个与 explanation 相关的问题,为什么 typescript 会这样。

【讨论】:

以上是关于打字稿不推断通用对象的值的主要内容,如果未能解决你的问题,请参考以下文章

打字稿推断传递了通用参数

打字稿:如何制作接受对象的类型,其键匹配通用但所有值都是值参数的映射函数

打字稿不正确的分配/映射到强类型对象[关闭]

如何使用打字稿中的查找来推断类型化的 mapValues?

打字稿中的通用对象类型

TypeScript 类型推断 - 函数的通用对象