typescript 筛选匹配接口的对象属性

qfe3c7zg  于 2023-02-13  发布在  TypeScript
关注(0)|答案(4)|浏览(203)

我有一些对象实现了一些接口,但它们也有额外的属性。当我开始序列化它们(保存在文件中)时,我希望删除所有这些额外的属性,只保留与接口匹配的属性。
有没有一种方法可以“清理”一个给定接口的对象?我试过

Object.getOwnPropertyNames(myObject)

获取对象属性的完整列表,并与接口属性的完整列表进行比较,但我无法找到获取接口属性列表的方法
编辑:我在这里找到了一种方法:How can I create an object based on an interface file definition in TypeScript?

var object = <IMyInterface>{};

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

mctunoxg

mctunoxg1#

验证代码:

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在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在Playground)

g0czyy6m

g0czyy6m2#

我真的很喜欢@Nitzan的回答,但是我遇到的一个问题是,当我更新类型时,硬编码到字符串数组中的键并不更新,这导致了错误,否则这些错误会被typescript捕获。因此,我建议也键入键字符串数组,以便typescript在您以后更改类型时也提示您更新它:

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];
    }
});
qmb5sa22

qmb5sa223#

这可以通过结合使用keyof运算符和Object.keys()来提取与接口中定义的属性相匹配的对象的键来实现:

interface IMyInterface {
  property1: string;
  property2: number;
}

function cleanObject<T>(obj: T, interfaceRef: T): T {
  const interfaceProperties = Object.keys(interfaceRef) as Array<keyof T>;
  const objectProperties = Object.keys(obj) as Array<keyof T>;

  objectProperties.forEach(property => {
    if (!interfaceProperties.includes(property)) {
      delete obj[property];
    }
  });

  return obj;
}

const myObject = { property1: 'value1', property2: 2, extraProperty: 'extraValue' };
const cleanedObject = cleanObject(myObject, <IMyInterface>{});

console.log(cleanedObject);
// Output: { property1: 'value1', property2: 2 }

基本上,cleanObject是一个泛型函数,它接受一个对象obj和一个接口引用interfaceRef
Object.keys()方法用于提取objinterfaceRef的键,并将它们转换为数组。keyof操作符用于确保数组只包含与相应对象或接口的属性匹配的键
最后,使用循环比较obj的属性与interfaceRef中定义的属性,如果obj中的属性不存在于interfaceRef中,则将其从obj中删除。
然后将清理后的对象作为函数的结果返回。
希望这能帮上忙...

ttp71kqs

ttp71kqs4#

您可以执行以下操作:

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>

相关问题