【问题标题】:How to compare two typed objects (with interface) in React?如何在 React 中比较两个类型化的对象(带接口)?
【发布时间】:2020-09-12 23:58:42
【问题描述】:

需要获取两个对象之间已更改属性的 delta (key/val)。 代码是打字稿。 这两个对象是由同一个接口创建的。

export interface ITestObj {
   att1: string;
   att2: string[];
   att3: string;
}

我收到一个错误,即对象的属性不能用作索引。 不能这样做:

if(objA['att1'] !== objB['att1']) {
}

为了解决这个问题,我尝试将界面修改为:

export interface ITestObj {
       [att1: string]: string;
       att2: string[];
       att3: string;
    }

但这无法做到,因为并非所有属性都是字符串(或数字......)。

如何获取objA和objB不同的属性?

非常感谢。

【问题讨论】:

  • 你能分享更多代码来帮助我们执行代码并解决问题吗?
  • 我没有任何错误。我忽略了第三个 sn-p。

标签: reactjs typescript react-functional-component


【解决方案1】:

您可以使用typeof() 进行值类型比较:

if (typeof objA.att1 !== typeof objB.att1) {
    // ...
}

请参阅 TypeScript 文档中的 typeof type guards

【讨论】:

    【解决方案2】:

    你可以试试

    if(objA.att1 !== objB.att1) {
    }
    

    但是更好的是使用

    if(JSON.stringify(objA) !== JSON.stringify(objB)) {
    }
    

    【讨论】:

      【解决方案3】:

      我尝试在以下代码中对几种解决方案进行细分:

      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;
      };
      

      但即使使用转换,您也无法使您的函数通用!转换不知道类型参数 T 将是什么,因为它取决于调用函数的位置,所以您无法提取其密钥!

      它与 TypeScript 本身有关,你必须在那儿帮忙:

      // 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 为您生成该数组。

      【讨论】:

        猜你喜欢
        • 2018-05-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-29
        • 1970-01-01
        • 2016-07-26
        • 2010-10-16
        相关资源
        最近更新 更多