如何避免JSON.parse reviver函数中返回any触发ESLint报错
TypeScript中JSON.parse使用reviver触发no-unsafe-return报错的处理方案
问题说明
在TypeScript + ESLint配置的项目中调用JSON.parse做反序列化时,若传入reviver函数对解析值做自定义转换,会遇到@typescript-eslint/no-unsafe-return报错。
TypeScript内置的JSON.parse类型定义中,reviver函数的签名如下:
JSON.parse(text: string, reviver?: ((this: any, key: string, value: any) => any) | undefined): any
由于reviver的入参value和返回值都被标注为any类型,当编写如下逻辑时,返回未做处理的value就会触发ESLint的不安全any返回报错:
const deserializedValue: unknown = JSON.parse(serializedValue, (key, value) => { if (value === 'foo') { return 'bar' } return value })
报错信息为:
5:4 error Unsafe return of an `any` typed value @typescript-eslint/no-unsafe-return
可行处理方案
不需要全局禁用lint规则,优先通过编码层面的类型调整规避报错,仅在必要时做局部规则豁免:
- 显式标注value的合法类型(推荐)
reviver处理的所有值都是JSON规范支持的合法解析结果,不存在无约束的任意值,可以先定义JSON合法值的递归类型,给reviver的value参数做显式类型标注,从根源上消除any类型:
该写法完全符合JSON解析的实际运行逻辑,不会引入额外类型风险,也不会触发lint报错。type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue } const deserializedValue: unknown = JSON.parse(serializedValue, (key, value: JsonValue) => { if (value === 'foo') { return 'bar' } return value }) - 返回时做类型断言
若不想额外定义递归类型,可以在返回默认值时将value断言为unknown类型,由于JSON.parse本身的返回值最终会被收窄为unknown,该断言不会破坏类型安全:const deserializedValue: unknown = JSON.parse(serializedValue, (key, value) => { if (value === 'foo') { return 'bar' } return value as unknown }) - 单行禁用lint规则(特殊场景使用)
若项目编码规范不允许修改参数类型或加类型断言,可仅针对返回值所在行禁用对应lint规则,禁止全局关闭@typescript-eslint/no-unsafe-return,避免漏掉其他业务代码中真实的不安全any返回问题:const deserializedValue: unknown = JSON.parse(serializedValue, (key, value) => { if (value === 'foo') { return 'bar' } // eslint-disable-next-line @typescript-eslint/no-unsafe-return return value })
提示:JSON反序列化的结果本身确实存在不确定性,因此将
JSON.parse的直接返回值标注为unknown是符合类型安全要求的做法,后续使用反序列化结果时再做具体的类型收窄即可。
内容的提问来源于stack exchange,提问作者slifty
相关产品推荐
相关产品推荐

