【问题标题】:Filter object properties matching interface过滤对象属性匹配界面
【发布时间】:2016-10-13 22:09:30
【问题描述】:

我有一些对象实现了一些接口,但它们也有额外的属性。 当我对它们进行序列化(以保存在文件中)时,我想删除所有这些额外的属性,并只保留与接口匹配的属性。

有没有办法“清理”关于给定接口的对象。 我正在尝试

Object.getOwnPropertyNames(myObject)

获取对象属性的完整列表,并与接口属性的完整列表进行比较,但我找不到获取接口属性列表的方法

编辑:我在这里找到了一种方法:How can I create an object based on an interface file definition in TypeScript?

var object = <IMyInterface>{};

但是我看到当我使用 Object.getOwnPropertyNames(myObject) 时,这仅适用于已定义的属性,如果未定义属性,则它不在结果中。有没有一种方法可以获取所有可用的属性,而不仅仅是定义的属性?

【问题讨论】:

  • 你能发布一个属性的例子吗?
  • 例如对于 Person 对象:姓名、姓氏、年龄、性别。并使用 IPerson 接口,例如:姓名、姓氏、年龄。我希望能够保存不包括“性别”属性的对象,因为它不在界面中
  • 接口在运行时不存在,所以你不能这样做。您可以做的是为每个接口创建一个列表,其中包含该接口的属性名称,然后在运行时对其进行迭代
  • @NitzanTomer 你能解释一下吗?我不明白

标签: angular typescript


【解决方案1】:

查看此代码:

interface MyInterface1 {
    field1: string;
    field2: string;
}

interface MyInterface2 {
    field3: string;
    field4: string;
}

let o1 = {
    field1: "field1",
    field2: "field2",
    fieldN: "fieldN"
} as MyInterface1;

let o2 = {
    field3: "field3",
    field4: "field4",
    fieldN: "fieldN"
} as MyInterface2;

编译成:

var o1 = {
    field1: "field1",
    field2: "field2",
    fieldN: "fieldN"
};
var o2 = {
    field3: "field3",
    field4: "field4",
    fieldN: "fieldN"
};

(code in playground)

所以你可以看到在编译的(js)代码中接口不存在,所以你无法知道(在运行时)你需要保留哪些属性。

你可以做的是:

let myInterface1Keys = ["field1", "field2"];
interface MyInterface1 {
    field1: string;
    field2: string;
}

let o1 = {
    field1: "field1",
    field2: "field2",
    fieldN: "fieldN"
} as MyInterface1;

let persistableO1 = {} as MyInterface1;
Object.keys(o1).forEach(key => {
    if (myInterface1Keys.indexOf(key) >= 0) {
        persistableO1[key] = o1[key];
    }
});

(code in playground)

【讨论】:

  • 是的,我认为这会起作用,这是我的最后选择,因为我不想创建(和维护)所有这些额外的变量
  • 如果你可以使用class而不是接口,那么装饰器可以用来做你想做的事。
  • 而不是 object.key().foreach 您可以从 lodash 中选择:persistableO1 = _.pick(o1, myInterface1Keys)
  • 这是旧的,但它从对象中选择属性,而不是从接口中。尽管我知道确实没有更好的选择。
【解决方案2】:

你可以这样做:

var app = angular.module("myapp", []);
app.controller("AppCtrl", function($scope){
  $scope.person = {
    name : "John",
    surname : "Doe",
    age : 50,
    gender : "male"
	};
});

app.filter("myfilter", function(){
  return function (input, excludeItem) {
    delete input[excludeItem];
    return input;
  }
});
<html>
  <head>
    <title>Solutions-1</title>
  </head>
  <body ng-app="myapp">
    <div ng-controller="AppCtrl">
      <div ng-repeat="(key, value) in person | myfilter:'gender'">{{key}} : {{value}}</div>
    </div>
    <script src = "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
  </body>
</html>

演示:http://codepen.io/Asit124/pen/ZOWJeM

【讨论】:

    【解决方案3】:

    我真的很喜欢@Nitzan 的回答,但是我遇到的一个问题是,当我更新我的类型时,硬编码到字符串数组中的键不会更新,从而导致错误,否则会被打字稿捕获。所以我建议你也输入键字符串数组,以便打字稿提示你更新它,如果你以后改变你的类型:

    
    interface MyInterface1 {
        field1: string;
        field2: string;
    }
    
    let o1 = {
        field1: "field1",
        field2: "field2",
        fieldN: "fieldN"
    } as MyInterface1;
    
    let myInterface1Keys: Array<keyof MyInterface1> = ["field1", "field2"]; //<--------
    
    let persistableO1 = {} as MyInterface1;
    Object.keys(o1).forEach(key => {
        if (myInterface1Keys.indexOf(key) >= 0) {
            persistableO1[key] = o1[key];
        }
    });
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-02
      • 1970-01-01
      • 2023-04-09
      • 2022-01-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多