类 在打字稿中进行数据水合/脱水
Classes with data hydration / dehydration in typescript
我想在 React + TS 前端和节点 + TS 后端之间共享 TS classes 或接口。问题是 TS 类型在编译时被剥离,所以当我想将 class 实例转换为 JSON.
时我不能使用它们
我想知道是否有任何解决方案可以在静态文件中描述我的对象,生成 TS classes,并使用该文件进行数据水合和脱水。一些属性是 moment.js
个对象和 Decimal.js
个对象。我正在寻找一种可以根据静态描述符完成转换的解决方案,我不需要为每个 属性 手动编写它。
HTTP请求中使用dehydrated格式,存储在DB(Firebase Firestore)中,前端直接读取。
我会使用很棒的 io-ts
库来解决这个问题。
The dehydrated format is used in HTTP request plus it's stored in the DB (Firebase Firestore) and accessed directly by the frontend for reading.
一般来说,我假设不同的层有不同的序列化格式。如果在您的特定情况下可以进行这种简化,那么
I was wondering if there are any solutions with which I could describe my object in a static file
使用 io-ts
,您可以将一组 codec
定义为代表您的域的 TypeScript 值。编解码器既是验证器又是(反)序列化器,因此您可以很好地将 class 实例序列化为 JSON 字符串,并且 vice-versa (前提是 JSON 是成功验证,然后使用适当的反序列化值实例化 class。
执行此类工作的简化且非常自定义的编解码器如下:
// 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 }'
除此之外,您通常还需要注意序列化某种标签,这样您就可以决定要尝试实例化哪个 class,只需查看普通的序列化 JSON 字符串。
您可能还想看看 io-ts-types
,它已经包含许多您可以重复使用的 ready-to-use 编解码器,例如 DateFromISOString
.
我想在 React + TS 前端和节点 + TS 后端之间共享 TS classes 或接口。问题是 TS 类型在编译时被剥离,所以当我想将 class 实例转换为 JSON.
时我不能使用它们我想知道是否有任何解决方案可以在静态文件中描述我的对象,生成 TS classes,并使用该文件进行数据水合和脱水。一些属性是 moment.js
个对象和 Decimal.js
个对象。我正在寻找一种可以根据静态描述符完成转换的解决方案,我不需要为每个 属性 手动编写它。
HTTP请求中使用dehydrated格式,存储在DB(Firebase Firestore)中,前端直接读取。
我会使用很棒的 io-ts
库来解决这个问题。
The dehydrated format is used in HTTP request plus it's stored in the DB (Firebase Firestore) and accessed directly by the frontend for reading.
一般来说,我假设不同的层有不同的序列化格式。如果在您的特定情况下可以进行这种简化,那么
I was wondering if there are any solutions with which I could describe my object in a static file
使用 io-ts
,您可以将一组 codec
定义为代表您的域的 TypeScript 值。编解码器既是验证器又是(反)序列化器,因此您可以很好地将 class 实例序列化为 JSON 字符串,并且 vice-versa (前提是 JSON 是成功验证,然后使用适当的反序列化值实例化 class。
执行此类工作的简化且非常自定义的编解码器如下:
// 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 }'
除此之外,您通常还需要注意序列化某种标签,这样您就可以决定要尝试实例化哪个 class,只需查看普通的序列化 JSON 字符串。
您可能还想看看 io-ts-types
,它已经包含许多您可以重复使用的 ready-to-use 编解码器,例如 DateFromISOString
.