typescript:如何在 Object.entries().forEach([key,value]) => 中正确键入键和值参数

Seb*_*n D 4 javascript typescript typescript-typings

我得到了一个具有特定键/值参数的对象,我想使用 Object 的entries() 方法和 Array 的 forEach() 方法对其进行迭代。但是我不明白如何输入此配置以避免打字稿错误:

\n
type objType = {\n  prop1: number | undefined;\n  prop2: number | undefined;\n  prop3: number | undefined;\n};\n\nconst obj: objType = {\n  prop1: 2,\n  prop2: 0,\n  prop3: undefined,\n};\n\n//1st attempt\nObject.entries(obj).forEach(([key, value]) => {\n  if (value === undefined || value < 5) obj[key] = 5;\n});\n\n//2nd attempt\nObject.entries(obj).forEach(\n  ([key, value]: [keyof objType, number | undefined]) => {\n    if (value === undefined || value < 5) obj[key] = 5;\n  }\n);\n
Run Code Online (Sandbox Code Playgroud)\n

key在第一次尝试中,我让打字稿推断(\xe2\x86\x92 string) 和value(\xe2\x86\x92 )的类型number|undefined。但在这种情况下,我在执行时遇到错误obj[key]

\n
\n

元素隐式具有“any”类型,因为“string”类型的表达式不能用于索引类型“objType”。在“objType”类型上找不到带有“string”类型参数的索引签名。

\n
\n

在第二次尝试中,我强制 的类型key对应于objusingkeyof运算符的键,但不允许这种类型定义,并且我收到以下消息:

\n
\n

类型为 '([key, value]: [keyof objType, number | undefined]) => void' 的参数不可分配给类型为 '(value: [string, number | undefined], index: number, array: [字符串,数字 | 未定义][]) => void'。参数“__0”和“value”的类型不兼容。\n键入“[string, number | undefined]' 不可分配给类型 '[keyof objType, number | undefined]'。\n源中位置 0 处的类型与目标中位置 0 处的类型不兼容。\n类型“string”不可分配给类型“keyof objType”。

\n
\n

我理解第一次尝试的失败,但不理解第二次的失败。为什么 TS 认为我想将字符串分配给字符串枚举,我猜要做相反的事情......?

\n

如何输入此配置的正确方法?

\n

Dra*_*g13 6

为什么

首先我们需要了解为什么会发生这种情况:让我们看一个最简单的例子:

const obj = {a: 1};
Object.keys(obj).forEach((key:keyof typeof obj)=> ''); // fails because Type 'string' is not assignable to type '"a"'
Run Code Online (Sandbox Code Playgroud)

发生这种情况是因为 TS 无法保证对象中没有其他键。因此,它不能保证密钥只是 a”。

就您而言,这意味着 TS 无法确保 的值obj[key]是数字。它可能是任何东西,因此 TS 会抛出错误。

例子

选项1

处理此问题的一种方法是强制 TS 使用您的类型:

//1st attempt
Object.entries(obj).forEach(([key, value]) => {
  if (value === undefined || value < 5) obj[key as keyof typeof obj] = 5;
});

//2nd attempt
Object.entries(obj).forEach(
  ([key, value]) => {
    if (value === undefined || value < 5) obj[key as keyof typeof obj] = 5;
  }
);

Run Code Online (Sandbox Code Playgroud)

如果您绝对确定不存在额外的密钥,那么这是可以的。

选项#2

另一种方法是将类型重新设计为更通用的类型:

type objType = {
    prop1: number | undefined;
    prop2: number | undefined;
    prop3: number | undefined;
}

const obj: Record<string, number | undefined> = {
    prop1: 2,
    prop2: 0,
    prop3: undefined,
};

//1st attempt
Object.entries(obj).forEach(([key, value]) => {
    if (value === undefined || value < 5) obj[key] = 5;
});

//2nd attempt
Object.entries(obj).forEach(
    ([key, value]) => {
        if (value === undefined || value < 5) obj[key] = 5;
    }
);
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,我们明确指出我们允许任何字符串键。

检查一些额外的详细信息