Is there a way in Typescript to extract values from JSON objects within an array, even when the property names are constantly changing?

As a newcomer to typescript, I am looking for a way to extract values from JSON objects within an array that have changing property names.

The code I have (simplified) is as follows:

const gridData = [
  { "source_language": "en", "word": "man", "character_grid": [["i", "q", "\u00ed", "l", "n", "n", "m", "\u00f3"], ["f", "t", "v", "\u00f1", "b", "m", "h", "a"], ... ], "target_language": "es" },
  ...
];

const gridDataInUse = gridData[0];

const selectedLetters = [{x: 6, y: 1, l: "h"}, {x: 6, y: 2, l: "o"}, ...]

const letterCoordinates: number[] = []
selectedLetters.forEach((letter => {
    letterCoordinates.push(letter.x);
    letterCoordinates.push(letter.y);
}));
const letterCoordinatesAsString = letterCoordinates.join(',');
const selectedWord = selectedLetters.map((letter) => {
    return letter.l;
}).join('');
console.log(gridDataInUse.word_locations[letterCoordinatesAsString]);

In this example, my intention is to retrieve the value "hombre" from the first JSON object in the array.

However, I encountered the following error message:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ "6,1,6,2,6,3,6,4,6,5,6,6": string; ... No index signature with a parameter of type 'string' was found on type '{ "6,1,6,2,6,3,6,4,6,5,6,6": string; ...

Can you guide me on how to resolve this error?

Thank you very much for your assistance!

Answer №1

For better compatibility with TypeScript, it is recommended to provide a type for your array as the comma in the word_location object might be causing confusion. Here's an example of how you can define the type:

interface gridItem {
    source_language: string,
    word: string,
    character_grid: Array<Array<string>>
    word_locations: Record<string, string>,
    target_language: string
}

const gridData:Array<gridItem> = [
  // Data objects here... 
];

// Sample usage
const gridDataInUse = gridData[0];

// Selected letters
const selectedLetters = [{x: 6, y: 1, l: "h"}, {x: 6, y: 2, l: "o"}, /* more letter objects */ ];

const letterCoordinates: number[] = []
selectedLetters.forEach((letter => {
    letterCoordinates.push(letter.x);
    letterCoordinates.push(letter.y);
}));
const letterCoordinatesAsString = letterCoordinates.join(',');
const selectedWord = selectedLetters.map((letter) => {
    return letter.l;
}).join('');
console.log(gridDataInUse.word_locations[letterCoordinatesAsString]);

If you'd like to see a working code example without errors, you can check out the link provided below.

View Working Code Example

Answer №2

If you are completely sure that each letterCoordinatesAsString you create will match a property in the object being examined, a simple solution is to specify in TypeScript that the word_locations object is of type Record<string, string>. This allows you to access the object using your letterCoordinatesAsString string:

const gridData: Array<{
    source_language: string;
    word: string;
    // ...
    word_locations: Record<string, string>;
}> = [
  { "source_language": "en", ...

TypeScript does not handle dynamic property names very gracefully. Another approach could be using a type assertion after an in check to confirm if the property exists on the object, indicating to the programmer that it is safe to access without providing TypeScript additional inference data:

const { word_locations } = gridDataInUse;
if (letterCoordinatesAsString in word_locations) {
    console.log((word_locations as Record<string, string | undefined>)[letterCoordinatesAsString]);
}

Applying as const typing could simplify things, converting the word_locations from a union (including possible undefined values) into the type of a straightforward object. While this may not make a difference when logging the result, it enables TypeScript to infer the value as a string rather than string | undefined, eliminating the need for the cumbersome as assertion.

const gridData = [
  { "source_language": "en", "word": ...
] as const;
// ...
if (letterCoordinatesAsString in word_locations) {
    console.log(word_locations[letterCoordinatesAsString]);
}

Answer №3

There seems to be an issue with the structure of your JSON. To correct it, you may need to add some curly brackets as shown below:

const info = [
          { details: { "2,3": "Sarah" }},
          { details: { "3,4": "Emily", "4,5": "David" }},
          { details: { "5,6": "Chris", "6,7": "Sophia" }}
         ];

Check out the corrected code on JSFiddle: https://jsfiddle.net/b9dACj2s/

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

How to Fix TypeScript React JS Lint Error: Missing Dependency in React Hook useEffect without Disabling Lint or Adding Additional Dependencies

As I build a Web application using React JS and TypeScript with React hooks, I encountered a warning when utilizing a custom hook in my Component. The warning states that the dependency 'productsHook' is missing in the useEffect hook. One way to ...

“How can Jest be used to test a redux toolkit slice that utilizes createAsyncThunk?”

I am looking to test the following simplified slice code snippet: interface MyState { data: any[]; } const initialState: MyState = { data: [], }; export const postData = createAsyncThunk( 'data/postData', async ( param: { data ...

Error encountered: Required closing JSX tag for <CCol> was missing

Encountered a strange bug in vscode...while developing an app with react.js. Initially, the tags are displaying correctly in the code file. However, upon saving, the code format changes causing errors during runtime. For instance, here is an example of the ...

Tips for utilizing global functions in VUE 2 CLI crowd

I have multiple components that require the same functions. Is there a way to avoid duplicating the code in each component and instead use it globally...? Even if I put the function in the App.vue, it still isn't accessible in the components. ...

Display or conceal form elements depending on the JSON response

Upon making an api call, a json Response is received with the following structure: {"Field":"Amount","FieldName":"Amount","FieldType":"Numeric","MaximumLength":128,"MinimumLength":0,"Options":"Mandatory"} This api call yields between 5-10 of these object ...

Files with extensions containing wildcards will trigger a 404 error when accessed from the public folder in NextJS

I have successfully set up my public folder to serve static files, however I am encountering an issue with files that have a leading dot in their filename (.**). Specifically, I need to host the "well-known" text file for apple-pay domain verification, wh ...

Adding the Bootstrap4 CDN seems to break the animations on my website

<div class="mySlides fade"> <img src="https://media.giphy.com/media/9JpsWBPgRtBDOYE6QB/source.gif" style="width:100%; height: 100%; border-radius: 0; "> </div> <div class="mySlides fade"> ...

I am attempting to initiate a new window or tab with POST data, but for some reason, it is not functioning correctly

One of the PHP-generated calls is as follows: <script> var copyrecipient = []; var customhintcopy = []; copyrecipient.push('customer'); copyrecipient.push('healthinsurance'); customhintcopy.push('4'); custom ...

Tips for creating a hierarchical multilevel datatable with JavaScript

I am currently working on implementing a multi-level datatable without relying on any external plugins or libraries. My goal is to achieve this using pure JavaScript, JQuery, or AngularJS. I have explored the following resources: Traverse all the Nodes of ...

I wonder if AngularJS offers a more efficient way to tally the total number of checkboxes

To determine if any checkbox is checked, I am currently using the following method: self.isButtonEnabled = function() { var selectLineCheckboxs = document.getElementsByClassName('selectLineRadioInput'), i = 0, checkboxLength = selectLineChe ...

What could be causing my Dojo Pie chart to vanish when I trigger the updateSeries function following an Ajax request?

I'm currently working on updating a dojo Pie chart using the updateSeries method. The method is called after an ajax request to retrieve an updated JavaScript array data. Below is the JavaScript code: var eventByReasonsData = .... //data is populate ...

Sequelize Authentication is unable to finalize

As I delve into the world of node.js and sequelize, I am encountering a persistent error: /home/cbaket/test/test.js:9 .complete(function(err) { ^ TypeError: undefined is not a function at Object.<anonymous> (/home/cbaket/test/test.js:9: ...

Ways to leverage Composite API in place of Mixin or Extends functionality

Currently, I am exploring the use of Vue3 for my project. One issue I am facing is that I need to create multiple components (SFC) with similar properties. I want to define these common properties using the composite API across all components, like so: con ...

Using Three.js to create a distorted texture video effect

Check out the example linked here for reference: In this particular project, there are two cylinders involved - an outer cylinder with an image texture and an inner cylinder with a video texture. Once the second cylinder is created and added to the scene, ...

Tips for selecting each item from an array in their own sequence? (using jQuery and JavaScript)

Here's my code: I've come to understand that my for loop assigns all array elements to the variable pickSound, hence it only plays the last element. How can I modify it so that each element plays in order and starts over once finished? functio ...

Exploring a nested JSON structure using AngularJS's Ng-Repeat directive

I am facing an issue with displaying all elements of subcategory using Ng-Repeat. I have managed to show all events from the selected category with this code, but I am unsure how to display all activities from a specific event. I currently have this code.. ...

Is there a way to prevent IntelliJ from creating .js files when working with .ts source code?

Working on a mixed Java/Typescript project with Maven as the build tool, I utilize the frontend-maven-plugin to successfully build from the command line. However, I am encountering an issue with IntelliJ 2018.2 where it keeps transpiling .js files for my . ...

Looking to execute a PHP file from HTML/JavaScript?

Greetings! I have a unique jQuery/javascript plugin that functions as a vertical ticker for news updates directly on my HTML website. Here is the code snippet: <script src="jquery.vticker-min.js"></script> <script type="text/ja ...

How to best handle dispatching two async thunk actions in Redux Toolkit when using TypeScript?

A recent challenge arose when attempting to utilize two different versions of an API. The approach involved checking for a 404 error with version v2, and if found, falling back to version v1. The plan was to create separate async thunk actions for each ver ...

Is there a way to ensure that a popup is scaled in proportion to its content?

Is there a way to make external links open in a new window with a size relative to the parent window, making it clear to the user? I initially used the target attribute but found a workaround like this: <a href="http://example.org" onclick="window.op ...