【问题标题】:Typescript: Filter Object by Interface or Class打字稿:按接口或类过滤对象
【发布时间】:2020-05-29 14:11:58
【问题描述】:

我想将 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: "..."
}

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

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

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

谢谢!

【问题讨论】:

    标签: javascript node.js typescript object


    【解决方案1】:

    如果我没听错的话,你:

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

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

    如果我是对的,你有两个选择:

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

    const unreliableObject = fetchFromApi();
    const result = new Result();
    
    if (typeof unreliableObject.name  === 'string') {
        result.name = unreliableObject.name;
    }
    

    这段代码比较没问题,除了它toooo冗长。

    作为更高级的解决方案,您可以创建 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 的 keyof

    主要思想是得到一个方案来解析原始响应。幸运的是,你已经拿到了。

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

    这可以使用:

    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,您不仅应该解析,还应该 validate 您正在解析的值。在另一种情况下,通过 API 提供的错误类型可能会破坏您的应用。

    您可以编写自己的验证(并不难)或采用现有的东西,例如yup

    【讨论】:

    • 嗨@Drag13,非常感谢您的回答!响应可能非常大,这就是为什么您的较低方法会更好地工作的原因。我刚刚试了一下,它似乎工作得很好。有什么办法,我可以通过编程方式获取 MyClass 的 keyof 而不是填充数组?
    • @lucbas 你好,抱歉回答晚了,我有一个周末:) 当然可以,我会在一小时内更新帖子。
    【解决方案2】:

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

    Plain TypeScript 通常不允许将纯类型信息传递给运行时代码。所以你在运行时看不到界面,也不知道它的字段是什么来过滤它们的。

    你可以得到一个类的属性名,但是你必须在你的代码中设置它们:

    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
    }
    

    或者,您可以通过enum 以这种奇怪的迂回方式声明接口,因为枚举是在运行时可访问的 TypeScript 构造之一:

    enum Props {
        value1 = "value1",
        value2 = "value2",
        value3 = "value3"
    };
    
    declare interface SampleInterface {
      [Props.value1]?: string;
      [Props.value2]?: string;
      [Props.value3]?: number;
    }
    
    class SampleClass implements SampleInterface {
      value1?: string = "";
      value2?: string = "";
      value3?: number = 0;
    }
    
    for (var k in Props) {
        console.log(k);  // prints value1, value2, value3
    }
    

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 2018-10-10
        • 2019-02-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-24
        • 2021-06-03
        • 1970-01-01
        • 2017-10-27
        相关资源
        最近更新 更多