【发布时间】:2021-12-13 03:07:21
【问题描述】:
如果我将 JSON 模式保存在像 f1040.json 这样的文件中,内容如下:
[
{
name: "L1",
type: "String"
},
{
name: "C2",
type: "Boolean"
},
{
name: "L3",
type: "String"
},
...
]
我想生成一个看起来像这样的类型:
type F1040 = {
L1: string;
C2: boolean;
L3: string;
...
}
如何在不手动指定每个字段的情况下生成此字段(有数百个字段)?我对解决方案的第一次尝试不是有效的打字稿(我认为我提供的映射类型不止一个),但希望这个无效的示例能够阐明我正在尝试做的事情:
import { f1040 } from "./f1040.json";
const bools = f1040.filter(e => e.type === "Boolean").map(e => name) as string[];
const strings = f1040.filter(e => e.type === "String").map(e => e.name) as string[];
export type F1040 = {
[key in (typeof bools)[number]]?: boolean;
[key in (typeof strings)[number]]?: string;
};
我不正确的解决方案的灵感来自一个类似但不同的问题的答案:TS create keys of new type from array of strings
Edit1:解决方案不需要是动态的,但如果它是构建时解决方案,那么它需要与 rollup 和 declarations bundler I'm using 配合得很好
Edit2:另一个不成功的尝试,这次使用@sinclair/typebox:
import { Static, Type } from "@sinclair/typebox";
import { f1040 } from "./f1040.json";
const F1040 = Type.Object({
...f1040
.filter(e => e.type === "Boolean")
.map(e => e.name)
.reduce((res, f) => ({ ...res, [f]: Type.Boolean() }), {}),
...f1040
.filter(e => e.type === "String")
.map(e => e.name)
.reduce((res, f) => ({ ...res, [f]: Type.String() }), {}),
});
export type F1040 = Static<typeof F1040>;
const f1040Data = {
L1: true,
C2: "Yea",
} as F1040
上面的尝试构建得很好,没有任何错误。这太糟糕了,因为最后的类型分配是错误的。这应该无法使用 TypeError 来构建,比如
属性“L1”的类型不兼容。 'boolean' 类型与 'string' 类型不可比较。
【问题讨论】:
-
您必须动态执行此操作吗?编写一些将您的 JSON 模式并在
.d.ts文件中写入interface或class定义的东西是微不足道的......事实上我确信有人已经这样做了。
标签: json typescript