JSON.parse(aString)
默认情况下键入为any
。但是,any
还包括函数,日期,正则表达式和其他无法解析的类。
现在,我怀疑如果我们利用ts 2.8中引入的条件类型和3.0的推断,我们会更加准确,但是我对如何做到这一点有些困惑。也许我缺少一些现有的基本类型,有人可以建议我吗?
const good: BasicType = JSON.parse(aString); // what I need
const bad: any = JSON.parse(aString); // what I do have now
答案 0 :(得分:1)
据我所知,TypeScript标准库中没有对应于可以从JSON序列化/反序列化的类型的内置类型名称。 GitHub中有一个issue建议添加一个,尽管看起来并没有太多动静。
幸运的是,您很容易为此创建自己的类型,例如在上述GitHub问题的注释中建议的this one:
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;
}
(请注意,如果您的代码在模块中,则需要使用global augmentation才能使以上代码正常工作
让我们看看它是否有效:
const x = JSON.parse('{"id": 123}'); // x is AnyJson
由于已知x
是AnyJson
而不是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标准库。如this comment中所述,AnyJson
类型为“在any
的分散距离内”。
好的,希望能有所帮助;祝你好运!