typescript 如何在ts中正确输入“JSON.parse()”?

xwmevbvl  于 2023-01-27  发布在  TypeScript
关注(0)|答案(1)|浏览(533)

JSON.parse(aString)默认类型为any。但是,any还包括函数、日期、正则表达式和其他无法解析的类。
现在我想如果我们使用ts 2.8中引入的条件类型和ts 3.0中的推理,我们会更准确,但是我有点纠结于如何去做,也许我缺少一些现有的基本类型,有人能给我建议吗?

const good: BasicType = JSON.parse(aString); // what I need
const bad: any = JSON.parse(aString); // what I do have now

[EDIT]现在可以使用递归类型,因此可以正确地输入JSON对象,typefest是一个实现示例。

axr492tv

axr492tv1#

据我所知,TypeScript标准库中没有内置类型名称来对应可以从JSON序列化/反序列化的类型,GitHub中有一个issue建议添加一个,尽管看起来没有太多的移动。
幸运的是,你可以很容易地为它创建自己的类型,就像前面提到的GitHub问题中的一条评论所建议的:

type AnyJson =  boolean | number | string | null | JsonArray | JsonMap;
interface JsonMap {  [key: string]: AnyJson; }
interface JsonArray extends Array<AnyJson> {}

然后,您可以使用declaration merging重载parse()方法,以返回AnyJson而不是any

interface JSON {
  parse(
    text: string,
    reviver?: ((this: any, key: string, value: any) => any) | undefined
  ): AnyJson;
}

(note如果您的代码位于模块中,则需要使用全局扩展才能使上述功能正常工作)
让我们看看它是否有效:

const x = JSON.parse('{"id": 123}'); // x is AnyJson

因为xAnyJson而不是any,所以现在可以对它进行类型保护,编译器应该更清楚它可能的结构:

if (x !== null && typeof x === "object" && !Array.isArray(x)) {
  // x narrowed to JsonMap
  Object.keys(x).forEach(k => {
    const y = x[k];
    // y is also AnyJson
    console.log("key=" + k + ", value=" + String(y));
  });
  // key=id, value=123
}

所以这一切都是可行的。也就是说,类型AnyJson实际上并不比any更具体。我想你会从可能的值/元素/属性中排除函数/方法中得到好处,这不是什么都不是......它可能没有足够的用处来保证修改TypeScript标准库。正如在这篇评论中所说的,AnyJson类型是"在any的分离距离内"。
好吧,希望能有所帮助;祝你好运!
链接到代码

相关问题