在解析JSON格式的字符串时,我得到一个linter错误:
let mqttMessage = JSON.parse(message.toString())
// ESLint: Unsafe assignment of an `any` value. (@typescript-eslint/no-unsafe-assignment)
我控制着message
的内容,所以我想告诉TS,JSON.parse()
产生的实际上是一个对象。我怎么能这么做?
注:我可以沉默警告,但我想了解是否有更好的方法来处理这个问题。
发布于 2021-08-07 10:00:38
问题是JSON.parse
返回一个any
类型。
这是公平的- TypeScript不知道它是要解析出一个字符串、一个数字还是一个对象。
你有个叫‘不允许将变量赋值为的规则。
所以你可以强迫你的JSON.parse结果
type SomeObjectIKnowAbout = {
};
const result = JSON.parse(message.toString()) as SomeObjectIKnowAbout;
在这个场景中,我喜欢做的是创建一个特定的解析函数,它将在运行时断言obj确实是您所说的形状,并且在您将代码编写为该对象时可以对其进行类型转换。
type SomeObjectIKnowAbout = {
userId: string;
}
type ToStringable = {
toString: () => string;
}
function parseMessage(message: ToStringable ) : SomeObjectIKnowAbout {
const obj = JSON.parse(message.toString()); //I'm not sure why you are parsing after toStringing tbh.
if (typeof obj === 'object' && obj.userId && typeof obj.userId === 'string') {
return obj as SomeObjectIKnowAbout;
}
else {
throw new Error ("message was not a valid SomeObjectIKnowAbout");
}
}
发布于 2021-08-07 09:56:18
JSON.parse
不是泛型的,所以我们不能提供一个泛型参数来完成它。
你有几个选择。
简单的是,由于JSON.parse
返回any
,所以只需定义要分配给它的类型:
let mqttMessage: MQTTMessage = JSON.parse(message.toString());
(我使用MQTTMessage
作为适当类型的替补。)
但是,这可能不足以为每个人提供足够的类型,因为它假设字符串定义了您期望它定义的内容。问题是,如果你在其他地方这样做,你就会重复这个假设。
相反,您可以定义一个函数:
function parseMQTTMessageJSON(json: string): MQTTMessage {
const x: object = JSON.parse(json);
if (x && /*...appropriate checks for properties here...*/"someProp" in x) {
return x as MQTTMessage;
}
throw new Error(`Incorrect JSON for 'MQTTMessage' type`);
}
那么您的代码是:
let mqttMessage = parseMQTTMessageJSON(message.toString());
发布于 2021-08-08 01:46:08
作为类型断言和运行时包装函数的替代方法,您可以利用声明合并为parse
方法添加一个泛型重载的全局JSON
对象。这将允许您通过预期的类型,并为您提供改进的IntelliSense,以防您在解析时使用reviver
:
interface JSON {
parse<T = unknown>(text: string, reviver?: (this: any, key: keyof T & string, value: T[keyof T]) => unknown): T
}
type Test = { a: 1, b: "", c: false };
const { a, b, c } = JSON.parse<Test>(
"{\"a\":1,\"b\":\"\",\"c\":false}",
//k is "a"|"b"|"c", v is false | "" | 1
(k,v) => v
);
或者,如果您依赖声明文件来扩展全局接口:
declare global {
interface JSON {
parse<T = unknown>(text: string, reviver?: (this: any, key: keyof T & string,
value: T[keyof T]) => unknown): T
}
}
https://stackoverflow.com/questions/68691208
复制相似问题