键入接收typescript中对象的键值对的回调

键入接收typescript中对象的键值对的回调,typescript,typescript-typings,Typescript,Typescript Typings,我在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

我在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 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:类型“string | number”不可分配给类型“never”。类型“string”不可分配给类型“never”。

据我所知,我必须将
值的类型声明为
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'.

这里是否还有实现有效键入的方法?

您可以在内部函数中为
引入泛型类型参数,以便Typescript能够匹配

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]);
    }
  }
}
函数forEachKey(obj:T,cb:(key:K,value:T[K])=>void:void{
用于(对象中的常数k){
if(Object.prototype.hasOwnProperty.call(obj,k)){
cb(k,obj[k]);
}
}
}

谢谢,这很有效。不幸的是,在将示例转换为我们的实现时,我遇到了更多的问题(请参见编辑)
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]);
    }
  }
}