我在 typescript 4.0.5 中编写了一个函数,它运行一个对象并为每个属性执行给定的回调,类似于 array.forEach (见下文)。
如果在 tsconfig 中设置了 noImplicitAny: true
,则只有所有属性共享相同类型时,该函数的类型才似乎有效。
export function forEachKey<T extends Object>(obj: T, cb: (key: Extract<keyof T, string>, value: T[keyof T]) => void): void {
for (const k in obj) {
if (Object.prototype.hasOwnProperty.call(obj, k)) {
cb(k, obj[k]);
}
}
}
以下示例没有错误:
interface TestNumber {
a: number;
b: number;
}
const t1Nr: TestNumber = { a: 1, b: 2 };
const t2Nr: TestNumber = { a: 3, b: 4 };
forEachKey(t1Nr, (key, value) => {
t2Nr[key] = value;
});
但是一旦存在不同类型的属性:
interface TestMixed {
a: number;
b: string;
}
const t1: TestMixed = { a: 1, b: '2' };
const t2: TestMixed = { a: 1, b: '2' };
forEachKey(t1, (key, value) => {
t2[key] = value; // error
});
我收到错误:
TS2322:输入“字符串|” number” 不可分配给类型“never”。类型“string”不可分配给类型“never”。
据我所知,我必须将 value
的类型声明为 T[key]
但我找不到方法来做到这一点。
有人知道如何修复打字吗? 提前致谢
编辑:
在 Aleksey 的回答使用这个简单的示例后,我尝试将该示例转换为我当前的实现。 我们有一个如下所示的类:
class TestMixed2Class implements TestMixed {
constructor (public a: number = 1, public b: string = '2', public c: number = 3) {}
setParams(params: TestMixed) {
forEachKey(params, (key, value) => this[key] = value); // error
}
}
这会导致错误
TS2322: Type 'TestMixed[K]' is not assignable to type 'this[K]'.
Type 'TestMixed' is not assignable to type 'this'.
'this' could be instantiated with an arbitrary type which could be unrelated to 'TestMixed'.
Type 'TestMixed[K]' is not assignable to type 'never'.
Type 'string | number' is not assignable to type 'never'.
Type 'string' is not assignable to type 'never'.
是否还有一种方法可以在这里实现有效的输入?
最佳答案
您可以在 key
的内部函数中引入泛型类型参数,这样 Typescript 将能够匹配 key
和 value
:
function forEachKey<T extends object>(obj: T, cb: <K extends keyof T>(key: K, value: T[K]) => void): void {
for (const k in obj) {
if (Object.prototype.hasOwnProperty.call(obj, k)) {
cb(k, obj[k]);
}
}
}
关于typescript - 在 typescript 中输入接收对象键值对的回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66013341/