How can I suggest the return type of a function that is out of my control?

When I attempt to parse a JSON-formatted string, a linter error is triggered:

let mqttMessage = JSON.parse(message.toString())

// ESLint: Unsafe assignment of an `any` value. (@typescript-eslint/no-unsafe-assignment)

Given that I am in control of the content of message, I'm interested in explicitly informing TypeScript that the result of JSON.parse() is actually an Object. Is there a recommended approach for achieving this?

Please note that although I could suppress the warning, I prefer to explore alternative solutions to address the issue.

Answer №1

One issue is that when using JSON.parse, it returns a type of any.

This makes sense because TypeScript cannot determine if the parsed result will be a string, number, or object.

Your linting rule advises against assigning variables as 'any'.

One way to handle this is by coercing the result of JSON.parse:

type SomeObjectIKnowAbout = {

}; 
const result = JSON.parse(message.toString()) as SomeObjectIKnowAbout; 

A better approach in such cases would be to create a dedicated parsing function that validates the shape of the object at runtime and performs the necessary type casting for easier handling:

type SomeObjectIKnowAbout = {
    userId: string; 
}

type ToStringable = {
    toString: () => string; 
}

function parseMessage(message: ToStringable ) : SomeObjectIKnowAbout {
    const obj = JSON.parse(message.toString()); //It is unclear why you are parsing after calling toString.

    if (typeof obj === 'object' && obj.userId && typeof obj.userId === 'string') {
        return obj as SomeObjectIKnowAbout; 
    }
    else {
        throw new Error ("message was not a valid SomeObjectIKnowAbout"); 
    }
}

Answer №2

JSON.parse is not a one-size-fits-all solution, so providing a generic argument is not possible.

You have a couple of choices to consider.

A straightforward approach would be to specify the type of the variable that you are assigning the result of JSON.parse to, since it returns any:

let mqttMessage: MQTTMessage = JSON.parse(message.toString());

(I've used MQTTMessage as an example type.)

However, this method may not be robust enough for all cases, as it assumes the string contains the expected data type and may necessitate repeated assumptions elsewhere in your code.

Alternatively, you could create a function:

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`);
}

Then you can use the function in your code like this:

let mqttMessage = parseMQTTMessageJSON(message.toString());

Answer №3

Instead of relying on type assertions and runtime wrapper functions, you have the option to employ declaration merging to enhance the global JSON object with a generic overload for the parse method. This enhancement allows you to specify the expected type and get better IntelliSense support if you utilize a reviver during parsing:

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
);

Alternatively, if you prefer using declaration files to extend global interfaces:

declare global {
  interface JSON {
    parse<T = unknown>(text: string, reviver?: (this: any, key: keyof T & string, 
  value: T[keyof T]) => unknown): T
  }
}

Playground

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the process for implementing custom color props with Material-UI v5 in a React TypeScript project?

Looking to enhance the MUI Button component by adding custom color props values? I tried following a guide at , but encountered errors when trying to implement it in a custom component. The custom properties created in createPalette.d.ts did not work as ex ...

Set up a Pinia store with a specific data type

Note: I am a beginner in JavaScript I am currently working on synchronizing an object with a Pinia store and a Python REST API. My goal is to define a type just once without having to duplicate it in the store. export const useTicketStore = defineStore(&a ...

Combining JSON payload values into an object

To ensure that only the attributes provided in a payload are updated in an 'Entity' object retrieved from a database, I aim to merge the REST PATH payload with the entity. This will guarantee that only the specified attributes in the patch payloa ...

How can I effectively store nested JSON data in a SQL Server database?

I am currently dealing with a nested JSON dataset that needs to be uploaded into SQL SERVER 2012. This JSON data consists of two main sections - one for columns and the other for rows. My task is to map the values from the rows section into their correspon ...

Working with JSON data and extracting specific information within the grades

Here is a JSON data structure that contains information about a student named Alice and her grades in various courses: { "student": [{ "cert_id": "59826ffeaa6-b986fc04d9de", "batch_id": "b3d68a-402a-b205-6888934d9", "name": "Alice", "pro ...

Error: The module parsing process failed due to the presence of an octal literal in strict mode. To resolve this issue,

I'm currently attempting to incorporate the following regular expression into Angular6: const regexp = new RegExp('^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\\1|(?:(?:29|30)(\/|-|\.)(?:0?[1,3-9]|1[0-2])\\2))(? ...

What is the best way to iterate through my array of objects using a forEach loop and assign a value to the property of any object that has an empty string?

Inquiry for Part 1: I am currently exploring the use of forEach loop to iterate through an array of objects. My goal is to update the property "profile_image_url" of objects that have an empty string as its value, setting it to a default link ("/media/arti ...

Can we use a switch statement instead of having multiple @Input()s in Angular?

When passing an attribute into my Angular component like this: <my-component myAttribute></my-component> I aim to modify a variable within the component that controls the CSS properties for width and height. To simplify, I have predefined at ...

Encounter an error parsing the package.json file. Confirmed that it is valid JSON

As I embark on creating my very first yeoman generator, I have encountered an issue when running yo to initiate the project. The error message I am receiving is as follows: npm ERR! install Couldn't read dependencies npm ERR! Darwin 14.0.0 npm ERR! a ...

Step-by-step guide on importing Nano (CouchDB) using Typescript

I am facing difficulty in importing and using nano in my node application. According to the documentation, the JavaScript way is: var nano = require('nano')('http://localhost:5984'); How can I achieve this with TypeScript? I attempt ...

Leveraging the capabilities of NodeJS, enhance your Winston file transport feature with

Looking for a way to log JSON objects with line breaks and tabs using Winston for logging to a file. I am currently trying to implement the formatter function. var winston = require('winston'); var moment = require('moment'); function ...

Perform an action after the Ngx Bootstrap modal has been hidden

My modal features a login button: <button type="button" (click)="save()" class="btn btn-primary"> login </button> Upon clicking the button, my desired outcome is to: first hide the modal, and second navigate to another route. However, ...

Querying JSON values in Postgres can be done using the JSON

Can you help with the PostgreSQL query equivalent of this SQL statement? SELECT * FROM table1 where JSON_VALUE(colB,'$.Items[0].Item') ='abc' I have consulted the PostgreSQL documentation but I keep getting an error saying "No functio ...

Struggling with utilizing data encoded by PHP into JSON format when working with JavaScript to showcase graphs using the chart.js library

My goal is to showcase a graph using the chart.js JavaScript library. I am retrieving data from a database in PHP and passing it to JavaScript using the json_encode() method to convert it into a JavaScript variable. The data consists of two fields from a & ...

Break apart each item in the loop and create a fresh array

My JSON API response is structured like this: Array ( [sections] => Array ( [0] => Array ( [id] => 115000089967 [url] => xxxxx [html_url] => ...

Encoding JSON and parsing data in case no results are retrieved

I am working on an AJAX project using PHP and JQuery, but I have encountered a problem. Specifically, I am facing an issue related to the dataType:"json" parameter in my Javascript code. Everything runs smoothly when the json_encode function returns rec ...

Error occurred while parsing the HTTP GET response (possible empty String?) - however, the body contains data

I have been working on a script in Javascript that communicates with a local Java Server through HTTP Requests. The structure of my requests is as follows: var req = $.ajax({ type : "GET", dataType : "json", url : "http ...

Rspec's include matcher is a useful tool for checking the presence of elements within Hash and String objects

Is there a way in Rspec to verify that all the fields in a Hash object : {"id"=>5392501, "owner"=>"cainlevy", "name"=>"photor", "url"=>"https://api.github.com/repos/cainlevy/photor", "description"=>"Photo Organizer (in Ruby)", "created_at"= ...

Comparing dates and times with Python by utilizing JSON information

Currently, I am in the process of writing a script that will load a JSON file and extract specific values based on a given timestamp. Below is the code snippet I have developed for this task. import json,datetime t1 = "2021-01-28T01:30:00Z" t2 = ...

What is the best way to create a dynamic icon using React and TypeScript?

Excuse me, I am new to using React and TypeScript. I'm having trouble getting the icon to change based on the status in AppointmentType. The body color is working fine, but the icons are not changing. Can someone please help me solve this issue? const ...