用于比较(和更新)Typescript 中对象的某些字段的类型定义
Type definition for comparing (and updating) certain fields of objects in Typescript
我想比较和分配两个对象的某些字段,比方说:
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
导致:“属性 'id' 在类型 'T' 上不存在”,我没有办法检查它 ('id' in right
)
第二次尝试:
leftToRight<T>(left: T, right: T & {id: number}, keys: Array<keyof T>): boolean
导致 right[key] = left[key]
的“类型 'T' 不可分配给类型 '{ id: number; }'”
第三次尝试:
leftToRight<T, U extends {id: number}>(left: T, right: U, keys: Array<keyof T & keyof U>): boolean
再次导致赋值错误 right[key] = left[key]
因为类型 T 和 U 可能完全不相关。
尝试使用 left: Partial<T>
,并断言 left[key]
不是未定义的 !
。
const left = { a: 1, ignored: 5};
const right = { a: 2, ignored: 6, id: 18 };
function leftToRight<T>(left: Partial<T>, right: T, keys: Array<keyof T>) {
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
}
编辑:
您已阐明您的要求,即 Left
和 Right
可能各自具有彼此不存在的属性。为了处理这种情况,我们需要两个泛型类型。
Right
是一个包含 id
的对象。我们希望所选键同时出现在 Left
和 Right
中,并且我们希望它们具有相同的值类型。
我将泛型 Keys
定义为 Right
的键的任何子集。我将 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
}
原答案:
在找到一个可行的方法之前,我尝试了一些方法。当然,这不是最干净的定义。我在使用泛型描述 Left
并添加 id
以获得 Right
时出错,但从 Right
中删除有效。
我们说 Right
是一个 {id: number}
属性 的对象, Left
必须具有 Right
除了 [=15= 之外的所有属性].为了让 keys
的元素出现在两个对象上,我们需要忽略 keyof Right
.
中的键 id
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
}
我想比较和分配两个对象的某些字段,比方说:
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
导致:“属性 'id' 在类型 'T' 上不存在”,我没有办法检查它 ('id' in right
)
第二次尝试:
leftToRight<T>(left: T, right: T & {id: number}, keys: Array<keyof T>): boolean
导致 right[key] = left[key]
第三次尝试:
leftToRight<T, U extends {id: number}>(left: T, right: U, keys: Array<keyof T & keyof U>): boolean
再次导致赋值错误 right[key] = left[key]
因为类型 T 和 U 可能完全不相关。
尝试使用 left: Partial<T>
,并断言 left[key]
不是未定义的 !
。
const left = { a: 1, ignored: 5};
const right = { a: 2, ignored: 6, id: 18 };
function leftToRight<T>(left: Partial<T>, right: T, keys: Array<keyof T>) {
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
}
编辑:
您已阐明您的要求,即 Left
和 Right
可能各自具有彼此不存在的属性。为了处理这种情况,我们需要两个泛型类型。
Right
是一个包含 id
的对象。我们希望所选键同时出现在 Left
和 Right
中,并且我们希望它们具有相同的值类型。
我将泛型 Keys
定义为 Right
的键的任何子集。我将 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
}
原答案:
在找到一个可行的方法之前,我尝试了一些方法。当然,这不是最干净的定义。我在使用泛型描述 Left
并添加 id
以获得 Right
时出错,但从 Right
中删除有效。
我们说 Right
是一个 {id: number}
属性 的对象, Left
必须具有 Right
除了 [=15= 之外的所有属性].为了让 keys
的元素出现在两个对象上,我们需要忽略 keyof Right
.
id
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
}