打字稿:按接口或类过滤对象

时间:2020-05-29 14:11:58

标签: javascript node.js typescript object

我想将API提供的对象同步到表。 该表在Sequelize中定义,并具有一个接口和一个类:

declare interface SampleInterface {
  value1?: string;
  value2?: string;
  value3?: number;
}
class SampleClass implements SampleInterface {
  value1?: string;
  value2?: string;
  value3?: number;
}

API的响应并不总是相同的,但可能看起来像这样:

const sampleResponse = {
  value2: "..."
  value3: 0
  value4: "..."
}

现在,我只想创建一个可以传递给具有匹配内容的续集的新对象,例如:

const filteredResponse = {
  value2: "..."
  value3: 0
}

如何将对象属性键与接口或类相匹配?

谢谢!

3 个答案:

答案 0 :(得分:1)

我认为您需要使用这样的自定义转换器来扩展TypeScript:ts-transformer-keys,以便能够获取接口的键并仅复制那些键来过滤响应。

普通TypeScript通常不允许将纯类型信息传递给运行时代码。因此,您在运行时看不到该接口,也无法知道要过滤它的字段是什么。

您可以获得类的属性名称,但必须在代码中进行设置:

Listbox

或者,您可以通过class SampleClass implements SampleInterface { value1?: string = ""; value2?: string = ""; value3?: number = 0; } var a = new SampleClass(); for (var k in a) { console.log(k); // prints value1, value2, value3 } 以这种怪异的回旋方式声明接口,因为枚举是可在运行时访问的TypeScript构造之一:

enum

答案 1 :(得分:1)

如果我正确地理解您,那么您:

具有:API产生的响应不是100%可预测的。

想要:从这个不受信任的来源创建该类的具体实例

如果我是对的,您有两种选择:

如果输入对象不是很大且不是动态对象,则可以明确地做所有事情:

const unreliableObject = fetchFromApi();
const result = new Result();

if (typeof unreliableObject.name  === 'string') {
    result.name = unreliableObject.name;
}

除了太冗长之外,此代码还可以。

作为更高级的解决方案,您可以创建TransformationMapper,如下所示:

class MyClass {
    name: string;
}

const expectedKeys: (keyof MyClass)[] = ['name'];
const data: any = { v: 1, name: '13212' };

const res = expectedKeys.reduce((result, fieldName) => {

    const value = data[fieldName];
    if (value != null) {
        result[fieldName] = data[fieldName]
    }

    return result;
}, new MyClass());

console.log(res);

更新

有什么办法,我可以通过编程方式获取MyClass的密钥

主要思想是获得一种解析原始响应的方案。幸运的是,您已经知道了。

因此,您需要:创建所需类的实例,并从中获取键:

这可以使用:

Object.keys()

Object.entries()

const data: any = {};

let result = new MyClass();
result = Object.keys(result).reduce((result, fieldName) => {

    const value = data[fieldName];
    if (value != null) {
        result[fieldName] = data[fieldName]
    }

    return result;
}, result)

但我也必须警告您。如果您不信任API,则不仅应解析,还应验证所解析的值。在另一种情况下,通过API提供的错误类型可能会破坏您的应用。

您可以编写自己的验证(并不难)或采用类似yup的内容

答案 2 :(得分:1)

如果您将类的字段设置为默认值并实例化该类,则可以通过编程方式获取类的字段

class SampleClass {
    value1?= "";
    value2?= "";
    value3?= 0;

}
var keys = Object.keys(new SampleClass()) as (keyof SampleClass)[];

var ob = { value1: "asd", value2: "sdad", value4: "xxx" };

var result: SampleClass = {};
for (var k of keys) {
    if (k in ob) { // remove this line if you want set missing fields to undefined
        result[k] = (ob as any)[k];
    }
}

console.log(result);