打字稿中具有数据水合/脱水的类

时间:2019-06-25 13:33:46

标签: node.js typescript hydration

我想在React + TS前端和node + TS后端之间共享TS类或接口。问题是TS类型在编译时被剥夺了,所以当我想将一个类实例转换成JSON时,我不能使用它们。

我想知道是否有什么解决方案可以在静态文件中描述对象,生成TS类以及将该文件用于数据水合和脱水。一些属性是moment.js对象和Decimal.js对象。我正在寻找一种可以基于静态描述符进行转换的解决方案,我不需要为每个属性手动编写转换。

HTTP请求中使用了脱水格式,并将其存储在DB(Firebase Firestore)中,并且前端可以直接访问以进行读取。

1 个答案:

答案 0 :(得分:2)

我会使用很棒的io-ts库来解决这个问题。

  

HTTP请求中使用了脱水格式,并将其存储在DB(Firebase Firestore)中,并且前端可以直接访问以进行读取。

通常,我会为不同的层假定不同的序列化格式。如果可以根据您的具体情况进行简化,那么?

  

我想知道是否有任何解决方案可以在静态文件中描述我的对象

使用io-ts,您可以定义一组codec作为代表您域的TypeScript值。编解码器既是验证器又是(反)序列化器,因此您可以很好地将类实例序列化为JSON字符串,反之亦然(前提是成功验证了JSON,然后使用适当的反序列化值实例化一个类)

执行此类工作的简化且非常自定义的编解码器如下:

// class definition:

class MyModel {
  constructor(readonly value: number) {}

  getValue() {
    return this.value;
  }
}

// codec definition:

import * as t from 'io-ts';
import { JSONFromString } from 'io-ts-types/lib/JSON/JSONFromString';

const MyModelFromString = new t.Type<MyModel, string, unknown>(
  'MyModel',
  (value): value is MyModel => value instanceof MyModel,
  str =>
    t.string
      .decode(str)
      .chain(JSONFromString.decode)
      .chain(json => t.type({ value: t.number }).decode(json))
      .map(({ value }) => new MyModel(value)),
  instance => JSON.stringify({ value: instance.value })
);

// usage:

MyModelFromString.decode('{ "value": 1 }').fold(
  errors => {
    console.error(errors);
  },
  inst => {
    // inst has type `MyModel` here
    console.log(inst.getValue());
  }
);

MyModelFromString.encode(new MyModel(2)); // '{ "value": 2 }'

最重要的是,您通常还需要序列化某种标签,以便您仅查看纯序列化的JSON字符串即可决定要实例化哪个类。

您可能还想看看io-ts-types,它已经包含了许多可以重复使用的即用型编解码器,例如DateFromISOString