我正在try 将属性值从源S
复制到目标T
.在以编程方式判断该字段是否存在后,我希望TS允许我访问它,但不会:
● Test suite failed to run
src/util/Copy.ts:18:18 - error TS2536: Type 'keyof T' cannot be used to index type 'S'.
18 return source[field] === target[field];
~~~~~~~~~~~~~
src/util/Copy.ts:33:11 - error TS2536: Type 'keyof S' cannot be used to index type 'T'.
33 match[field] = source[field];
~~~~~~~~~~~~
我可以使源从目标扩展到只接受这两种类型的字段.但我的实用程序方法应该处理完全不同的类型.以下是失败的代码
export function copyFieldsWhenMatching<S extends object, T extends object>(
sourceArray: S[],
targetArray: T[],
equalFields: (keyof T)[],
fieldsToCopy: (keyof S)[],
allowMultipleOccurrences: boolean
): T[] {
const toReturn = [...targetArray];
for (const source of sourceArray) {
// Find matches based on equalFields
const matches = toReturn.filter((target) => {
return equalFields.every((field) => {
// eslint-disable-next-line no-prototype-builtins
if (source.hasOwnProperty(field) && target.hasOwnProperty(field)) {
return source[field] === target[field];
}
return true; // Property doesn't exist in either source or target; continue matching.
});
});
if (!allowMultipleOccurrences && matches.length > 1) {
throw new DuplicateMatchesError(
"More than one match found for the source object.",
matches
);
} else if (matches.length >= 1 || allowMultipleOccurrences) {
// Copy fields from source to matches
for (const match of matches) {
for (const field of fieldsToCopy) {
match[field] = source[field];
}
}
}
}
return toReturn;
}
这就是我如何破解它以通过(将目标投射到源,反之只是为了通过).这就把我带到了标题中的问题:
有没有一种更干净的方法来更新keyof T的价值?
import { DuplicateMatchesError } from "../errors";
export function copyFieldsWhenMatching<S extends object, T extends object>(
sourceArray: S[],
targetArray: T[],
equalFields: (keyof T)[],
fieldsToCopy: (keyof S)[],
allowMultipleOccurrences: boolean,
): T[] {
const toReturn = [...targetArray];
for (const source of sourceArray) {
// Find matches based on equalFields
const matches = toReturn.filter((target) => {
return equalFields.every((field) => {
// eslint-disable-next-line no-prototype-builtins
if (source.hasOwnProperty(field) && target.hasOwnProperty(field)) {
return (
// dirty assertion to hack TS
(source as unknown as T)[field] ===
target[field]
);
}
return true; // Property doesn't exist in either source or target; continue matching.
});
});
if (!allowMultipleOccurrences && matches.length > 1) {
throw new DuplicateMatchesError(
"More than one match found for the source object.",
matches,
);
} else if (matches.length >= 1 || allowMultipleOccurrences) {
// Copy fields from source to matches
for (const match of matches) {
for (const field of fieldsToCopy) {
// dirty assertion to hack TS
(match as unknown as S)[field] = source[field];
}
}
}
}
return toReturn;
}