我正在写一个函数

const safeJSONParse = <T>(json: string, default?: T) : T | unknown => {
 try {
  return JSON.parse(json) as T ?? default
 }
 catch (e){
  return default
 }
}

它可以使用"坏"的json个字符串,但如果对象的类型不同于T,它仍然返回错误类型的对象,而不是默认值.

如果返回的对象不是类型T,则返回默认值,是否有一种方法可以使其工作.

推荐答案

如果返回的对象不是类型T,则返回默认值,是否有一种方法可以使其工作.

仅通过添加在运行时从JSON.parse判断结果的验证代码.非类型化世界和类型化世界之间的这些边缘总是提出这种挑战.

有一些库可以帮助您使用它们的方法编写形状(类型)的定义,并返回both运行时验证函数和TypeScript类型.我现在使用的是zod,但它不是唯一的一个在那里.


FWIW,这里有一个使用zod的例子,但是,还有其他的库,或者您可以为您的类型编写自己的自定义代码.

首先,定义了模式,并从中提取一个方便的类型别名:

// A user with a `name` and `email`, both strings
const userSchema = z.object({
    name: z.string(),
    email: z.string().email(), // Zod has some validators for common things like email addresses
});
type User = z.infer<typeof userSchema>;

在这里,User类型是{name: string; email: string;}.

然后你的函数将接受并使用Zod schema:

const safeJSONParse = <Schema extends ZodTypeAny>(
    json: string,
    schema: Schema,
    defaultValue?: z.infer<Schema>
): z.infer<Schema> | undefined => {
    try {
        const result = schema.parse(JSON.parse(json));
        return result;
    } catch (e: any) {
        return defaultValue;
    }
};

然后,在解析用户的JSON时使用该模式:

const user = safeJSONParse(userJson, userSchema);
if (user) {
    // It's valid
    console.log(user.name);
}

Playground example

Typescript相关问答推荐

我用相同的Redux—Toolkit查询同时呈现两个不同的组件,但使用不同的参数

webpack错误:模块找不到.当使用我的其他库时,

TypeScript:在作为参数传递给另一个函数的记录中对函数的参数实现类型约束

使用axios在ngOnInit中初始化列表

打印脚本中的动态函数重载

如何在编译时为不带常量的参数引发错误

如何解决类型T不能用于索引类型{ A:typeof A; B:typeof B;. }'

如何在NX工作区项目.json中设置类似angular.json的两个项目构建配置?

如何在方法中正确地传递来自TypeScrip对象的字段子集?

声明文件中的类型继承

如何从输入中删除值0

为什么我在这个重载函数中需要`as any`?

编译TypeScrip项目的一部分导致错误

如何在Angular 服务中制作同步方法?

如何避免从引用<;字符串&>到引用<;字符串|未定义&>;的不安全赋值?

为什么发送空字段?

如何在Nextjs路由处理程序中指定响应正文的类型

对于VUE3,错误XX不存在于从不存在的类型上意味着什么?

如何确定剧作家中给定定位器的值?

TS 条件类型无法识别条件参数