Я попытался дать разбивку нескольких решений в следующем коде:
type A = {
att1: string;
att2: string[];
att3: string[];
};
const compare = <T extends {}>(a: T, b: T): boolean => {
// Now there is several ways of doing this, all come with pros and cons
// 1. If you are absolutely certain that the objects have ALL the attributes
// from interface T (and no other attributes hidden from TypeScript)
// you can just well use something like isEqual from lodash or similar
// OR take the keys of one of your objects which will give you an array:
//
// const keys = ['att1', 'att2', 'att3']
//
// And you need to tell TypeScript that you are sure that these keys are exactly the ones from interface T
// by casting the string[] (that you get from Object.keys) to K[]
type K = keyof T;
const keys = Object.keys(a) as K[];
// Then finally loop over those keys and do the comparison that you want, I just sketched a thing here
//
// Note that to compare the string arrays you will need something more sophisticated than '==='!
for (const key of keys) {
if (a[key] !== b[key]) return false;
}
// 2. If you are not sure about what attributes there might be but the interfaces you need to compare
// are always the same (i.e. you don't need compare() to be generic)
//
// In this case you can either store the keys you expect in a hard-coded array:
type KA = keyof A;
const hardcodedKeys: KA[] = ['att1', 'att2', 'att3'];
// And again do your comparison here
// You can also go fancy and use something like ts-transformer-keys:
// https://www.npmjs.com/package/ts-transformer-keys
// which will give you the list of keys for a small price of hooking up the TypeScript transform
// And again do your comparison here
return true;
};
Но даже с преобразованием вы не сможете сделать свою функцию generi c! Преобразование не знает, каким будет параметр типа T
, потому что он зависит от того, где вызывается функция, поэтому вы не можете извлечь ее ключи!
Это связано с самим TypeScript, вы должны дать ему hand there:
// You will need to pass the array of keys to the function explicitly
// and let TypeScript just check that what you passed actually are keys of T
const compareProperties = <T extends {}>(a: T, b: T, keys: (keyof T)[]): boolean => {
for (const key of keys) {
if (a[key] !== b[key]) return false;
}
return true;
};
Опять же, вы можете использовать ts-transformer-keys
, чтобы сгенерировать этот массив для вас во время компиляции.