用于比较(和更新)Typescript中对象的某些字段的类型定义

用于比较(和更新)Typescript中对象的某些字段的类型定义,typescript,typescript-generics,typing,Typescript,Typescript Generics,Typing,我想比较和分配两个对象的某些字段,比如: const left = { a: 1, ignored: 5, something: 7 }; const right = { a: 2, ignored: 6, else: 8, id: 18 }; 我想调用leftToRight(left,right,['a']),然后right应该是: { a: 1, ignored: 6, id: 18 } 我想调用其他函数并传递right.id,我知道它确实存在于第二个参数中 我目前的做法是: leftT

我想比较和分配两个对象的某些字段,比如:

const left = { a: 1, ignored: 5, something: 7 };
const right = { a: 2, ignored: 6, else: 8, id: 18 };
我想调用
leftToRight(left,right,['a'])
,然后
right
应该是:

{ a: 1, ignored: 6, id: 18 }
我想调用其他函数并传递right.id,我知道它确实存在于第二个参数中

我目前的做法是:

leftToRight(left, right, keys) {
  let changed = false;
  
  for (const key of keys) {
    if (!Object.is(left[key], right[key])) {
      right[key] = left[key];
      changed = true;
    }
  }

  doSomething(right.id)

  return changed
}
我正在努力找到合适的类型定义:-(

初步做法:

leftToRight<T>(left: T, right: T, keys: Array<keyof T>): boolean
导致
right[key]=left[key]

第三次尝试:

leftToRight<T>(left: T, right: T & {id: number}, keys: Array<keyof T>): boolean
leftToRight<T, U extends {id: number}>(left: T, right: U, keys: Array<keyof T & keyof U>): boolean
leftToRight(左:T,右:U,键:数组):布尔值

再次导致赋值
right[key]=left[key]
出错,因为类型T和U可能完全不相关。

尝试
left:Partial
,并断言
left[key]
没有用
定义!

:

const left={a:1,忽略:5};
const right={a:2,忽略:6,id:18};
函数leftToRight(左:部分,右:T,键:数组){
让改变=错误;
for(键的常数键){
如果(!Object.is(左[键]、右[键]){
右[键]=左[键]!;
更改=正确;
}
}
//doSomething(右.id)
换回
}
编辑:

您已经澄清了您的需求,即
可能各自具有其他属性中不存在的属性。要处理此场景,我们需要两种泛型类型

Right
是一个包含
id
的对象。我们希望所选的键同时出现在
Left
Right
中,并且我们希望它们具有相同的值类型。 我将通用
定义为
键的任何子集。我将
定义为包含所有这些键的
的子集

function leftToRight<Right extends {id: number}, Keys extends keyof Right>(
  left: Pick<Right, Keys>, right: Right, keys: Keys[]
) {
  let changed = false;
  
  for (const key of keys) {
    if (!Object.is(left[key], right[key])) {
      right[key] = left[key];
      changed = true;
    }
  }

  doSomething(right.id)

  return changed
}

id
字段应该是
string
还是
number
?我更正了这个问题。它是一个数字。我会使用
leftToRight(left:T,right:T&{id:number},keys:Array):布尔值
(right as T)[key]=left[key]或类似的方法来消除该错误;我正在寻找编译器在将
T[keyof T]
分配给
(T&{id:number})[keyof T])
时出现问题的原因,但我还没有找到任何东西。如果我使用:
函数leftToRight(左:部分,右:T,键:数组)
,这似乎是可行的。你知道如何避免非空断言吗?不知道你避免非空断言的动机是什么,所以我不知道这是否更好,但你可以将
转换为
t
。示例:
right[key]=(left as T)[key]
我想避免我的衣帽匠抱怨;-)以及在运行时检测到可能在编译期间检测到的错误的情况(在严格的空检查模式下)。在这种情况下,
left[key]
是未定义的,因此,right[key]将是未定义的,如果后续代码没有预料到这一点,则可能会导致问题。然而,这可能是一个学术问题。所以,谢谢你的回答。它做它应该做的:)谢谢你的解决方案。我的问题不够清楚(将添加):
left
不一定具有
right
的所有属性(反之亦然)。所以
right
始终具有
id
left
right
具有任何属性,并且
只能是共享属性,对吗?我们需要(至少)两个泛型,但我想我能做到。我看看。。。
function leftToRight<Right extends {id: number}, Keys extends keyof Right>(
  left: Pick<Right, Keys>, right: Right, keys: Keys[]
) {
  let changed = false;
  
  for (const key of keys) {
    if (!Object.is(left[key], right[key])) {
      right[key] = left[key];
      changed = true;
    }
  }

  doSomething(right.id)

  return changed
}
function leftToRight<Right extends {id: number}>(
  left: Omit<Right, 'id'>, right: Right, keys: (Exclude<keyof Right, 'id'>)[]
) {
  let changed = false;
  
  for (const key of keys) {
    if (!Object.is(left[key], right[key])) {
      right[key] = left[key];
      changed = true;
    }
  }

  doSomething(right.id)

  return changed
}