Home > Back-end >  Typescript: How can I extract the value from JSON objects inside an array with changing property nam
Typescript: How can I extract the value from JSON objects inside an array with changing property nam

Time:02-21

I'm new to typescript and would like to extract the value from JSON objects inside an array with changing property names.

My (simplified) code 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"], ["h", "j", "\u00e9", "t", "e", "t", "o", "z"], ["x", "\u00e1", "o", "i", "e", "\u00f1", "m", "\u00e9"], ["q", "\u00e9", "i", "\u00f3", "q", "s", "b", "s"], ["c", "u", "m", "y", "v", "l", "r", "x"], ["\u00fc", "\u00ed", "\u00f3", "m", "o", "t", "e", "k"], ["a", "g", "r", "n", "n", "\u00f3", "s", "m"]], "word_locations": { "6,1,6,2,6,3,6,4,6,5,6,6": "hombre" }, "target_language": "es" },
  { "source_language": "en", "word": "woman", "character_grid": [["v", "\u00e1", "q", "t", "b", "f", "q"], ["y", "x", "i", "a", "\u00fc", "v", "a"], ["r", "d", "y", "\u00ed", "t", "n", "a"], ["f", "v", "\u00f3", "w", "l", "a", "v"], ["b", "u", "\u00fa", "j", "q", "h", "\u00e1"], ["c", "o", "m", "u", "j", "e", "r"], ["h", "o", "d", "\u00fa", "w", "d", "\u00fc"]], "word_locations": { "2,5,3,5,4,5,5,5,6,5": "mujer" }, "target_language": "es" },
  { "source_language": "en", "word": "boy", "character_grid": [["x", "c", "e", "x", "c", "i", "o"], ["e", "z", "q", "r", "h", "w", "y"], ["\u00f1", "\u00e9", "\u00f1", "w", "i", "n", "\u00e1"], ["o", "l", "a", "\u00e1", "c", "i", "n"], ["r", "v", "\u00f1", "s", "o", "\u00f1", "w"], ["k", "m", "w", "a", "\u00fc", "o", "w"], ["\u00f3", "r", "\u00fa", "b", "l", "g", "\u00fa"]], "word_locations": { "5,2,5,3,5,4,5,5": "ni\u00f1o", "4,0,4,1,4,2,4,3,4,4": "chico" }, "target_language": "es" },
  { "source_language": "en", "word": "girl", "character_grid": [["o", "s", "\u00f3", "x", "h", "\u00f1", "h"], ["\u00fc", "r", "g", "o", "l", "\u00fa", "b"], ["a", "t", "c", "h", "i", "c", "a"], ["u", "\u00fa", "r", "w", "\u00e1", "t", "\u00e9"], ["p", "n", "v", "r", "q", "m", "l"], ["f", "d", "t", "e", "a", "\u00f3", "l"], ["u", "t", "n", "i", "\u00f1", "a", "s"]], "word_locations": { "2,2,3,2,4,2,5,2,6,2": "chica", "2,6,3,6,4,6,5,6": "ni\u00f1a" }, "target_language": "es" },
  { "source_language": "en", "word": "am", "character_grid": [["d", "c", "e", "h", "p"], ["f", "e", "\u00fc", "p", "t"], ["s", "s", "\u00f3", "\u00ed", "l"], ["o", "s", "\u00ed", "\u00f1", "a"], ["y", "g", "i", "o", "n"]], "word_locations": { "0,2,0,3,0,4": "soy" }, "target_language": "es" },
  { "source_language": "en", "word": "she", "character_grid": [["z", "n", "w", "f", "m", "\u00e9"], ["d", "\u00f3", "q", "w", "n", "e"], ["z", "\u00e1", "v", "e", "\u00f3", "l"], ["r", "c", "z", "z", "m", "l"], ["\u00fc", "m", "\u00e1", "\u00fc", "n", "a"], ["e", "a", "e", "x", "\u00f1", "h"]], "word_locations": { "5,1,5,2,5,3,5,4": "ella" }, "target_language": "es" },
  { "source_language": "en", "word": "apple", "character_grid": [["\u00fa", "k", "\u00fc", "b", "\u00ed", "n", "z", "d", "o"], ["u", "\u00e1", "n", "g", "e", "y", "z", "o", "\u00f1"], ["o", "\u00e9", "\u00fa", "\u00e1", "v", "e", "x", "u", "m"], ["c", "w", "d", "z", "t", "k", "m", "l", "a"], ["u", "b", "o", "w", "\u00ed", "a", "u", "q", "n"], ["g", "s", "m", "e", "c", "n", "k", "\u00fa", "z"], ["a", "o", "v", "t", "p", "\u00fa", "\u00e9", "k", "a"], ["f", "j", "i", "j", "n", "i", "b", "\u00f3", "n"], ["s", "q", "l", "j", "j", "f", "q", "g", "a"]], "word_locations": { "8,2,8,3,8,4,8,5,8,6,8,7,8,8": "manzana" }, "target_language": "es" },
  { "source_language": "en", "word": "eat", "character_grid": [["i", "a", "c", "j", "r", "w"], ["k", "b", "n", "o", "u", "v"], ["v", "x", "z", "f", "m", "a"], ["u", "l", "o", "p", "e", "o"], ["l", "\u00fa", "\u00e9", "q", "j", "e"], ["a", "h", "\u00fa", "l", "k", "w"]], "word_locations": { "2,0,3,1,4,2,5,3": "como" }, "target_language": "es" },
  { "source_language": "en", "word": "bread", "character_grid": [["\u00fc", "\u00e1", "p", "a", "n"], ["k", "a", "k", "m", "l"], ["a", "x", "q", "e", "h"], ["p", "s", "a", "j", "\u00ed"], ["\u00e1", "q", "l", "j", "l"]], "word_locations": { "2,0,3,0,4,0": "pan" }, "target_language": "es" }
];

const gridDataInUse = gridData[0];

const selectedLetters = [{x: 6, y: 1, l: "h"}, {x: 6, y: 2, l: "o"}, {x: 6, y: 3, l: "m"}, {x: 6, y: 4, l: "b"}, {x: 6, y: 5, l: "r"}, {x: 6, y: 6, l: "e"}]

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

My goal in this example is to extract "hombre" from the first JSON object in the array.

However, I get 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; "2,5,3,5,4,5,5,5,6,5"?: undefined; "5,2,5,3,5,4,5,5"?: undefined; "4,0,4,1,4,2,4,3,4,4"?: undefined; "2,2,3,2,4,2,5,2,6,2"?: undefined; "2,6,3,6,4,6,5,6"?: undefined; ... 4 more ...; "2,0,3,0,4,0"?: undefined; } | ... 7 more ... | { ...; }'. 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; "2,5,3,5,4,5,5,5,6,5"?: undefined; "5,2,5,3,5,4,5,5"?: undefined; "4,0,4,1,4,2,4,3,4,4"?: undefined; "2,2,3,2,4,2,5,2,6,2"?: undefined; "2,6,3,6,4,6,5,6"?: undefined; ... 4 more ...; "2,0,3,0,4,0"?: undefined; } | ... 7 more ... | { ...; }'.(7053)

How can I solve this error?

Thanks a lot for your help!

CodePudding user response:

If you're absolutely certain that every letterCoordinatesAsString you construct will have a matching property in the object you're looking at, a simple enough fix would be to tell TS that the word_locations object is a Record<string, string>, allowing you to look up the object with your letterCoordinatesAsString string:

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

TypeScript generally doesn't play as nicely with dynamic property names as would be ideal. Another option is to resort to a type assertion after an in check, that tests whether the property exists on the object, telling the programmer that it's safe to access, but without giving TypeScript more information to infer from.

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

Typing the data as const could help, turning the word_locations from a union (with undefined possible values) into the type of a much simpler object. This won't affect things if you're just logging the result, but it'll let TS infer the value as a string, and not as string | undefined, and lets you avoid the ugly as assertion.

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

CodePudding user response:

Please Provide a type to your array, TS is getting confused because of the "," in your word_location object, following will work

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

const gridData:Array<gridItem> = [
  { "source_language": "en", "word": "man", "character_grid": [["i", "q", "\u00ed", "l", "n", "n", "m", "\u00f3"], ["f", "t", "v", "\u00f1", "b", "m", "h", "a"], ["h", "j", "\u00e9", "t", "e", "t", "o", "z"], ["x", "\u00e1", "o", "i", "e", "\u00f1", "m", "\u00e9"], ["q", "\u00e9", "i", "\u00f3", "q", "s", "b", "s"], ["c", "u", "m", "y", "v", "l", "r", "x"], ["\u00fc", "\u00ed", "\u00f3", "m", "o", "t", "e", "k"], ["a", "g", "r", "n", "n", "\u00f3", "s", "m"]], "word_locations": { "6,1,6,2,6,3,6,4,6,5,6,6": "hombre" }, "target_language": "es" },
  { "source_language": "en", "word": "woman", "character_grid": [["v", "\u00e1", "q", "t", "b", "f", "q"], ["y", "x", "i", "a", "\u00fc", "v", "a"], ["r", "d", "y", "\u00ed", "t", "n", "a"], ["f", "v", "\u00f3", "w", "l", "a", "v"], ["b", "u", "\u00fa", "j", "q", "h", "\u00e1"], ["c", "o", "m", "u", "j", "e", "r"], ["h", "o", "d", "\u00fa", "w", "d", "\u00fc"]], "word_locations": { "2,5,3,5,4,5,5,5,6,5": "mujer" }, "target_language": "es" },
  { "source_language": "en", "word": "boy", "character_grid": [["x", "c", "e", "x", "c", "i", "o"], ["e", "z", "q", "r", "h", "w", "y"], ["\u00f1", "\u00e9", "\u00f1", "w", "i", "n", "\u00e1"], ["o", "l", "a", "\u00e1", "c", "i", "n"], ["r", "v", "\u00f1", "s", "o", "\u00f1", "w"], ["k", "m", "w", "a", "\u00fc", "o", "w"], ["\u00f3", "r", "\u00fa", "b", "l", "g", "\u00fa"]], "word_locations": { "5,2,5,3,5,4,5,5": "ni\u00f1o", "4,0,4,1,4,2,4,3,4,4": "chico" }, "target_language": "es" },
  { "source_language": "en", "word": "girl", "character_grid": [["o", "s", "\u00f3", "x", "h", "\u00f1", "h"], ["\u00fc", "r", "g", "o", "l", "\u00fa", "b"], ["a", "t", "c", "h", "i", "c", "a"], ["u", "\u00fa", "r", "w", "\u00e1", "t", "\u00e9"], ["p", "n", "v", "r", "q", "m", "l"], ["f", "d", "t", "e", "a", "\u00f3", "l"], ["u", "t", "n", "i", "\u00f1", "a", "s"]], "word_locations": { "2,2,3,2,4,2,5,2,6,2": "chica", "2,6,3,6,4,6,5,6": "ni\u00f1a" }, "target_language": "es" },
  { "source_language": "en", "word": "am", "character_grid": [["d", "c", "e", "h", "p"], ["f", "e", "\u00fc", "p", "t"], ["s", "s", "\u00f3", "\u00ed", "l"], ["o", "s", "\u00ed", "\u00f1", "a"], ["y", "g", "i", "o", "n"]], "word_locations": { "0,2,0,3,0,4": "soy" }, "target_language": "es" },
  { "source_language": "en", "word": "she", "character_grid": [["z", "n", "w", "f", "m", "\u00e9"], ["d", "\u00f3", "q", "w", "n", "e"], ["z", "\u00e1", "v", "e", "\u00f3", "l"], ["r", "c", "z", "z", "m", "l"], ["\u00fc", "m", "\u00e1", "\u00fc", "n", "a"], ["e", "a", "e", "x", "\u00f1", "h"]], "word_locations": { "5,1,5,2,5,3,5,4": "ella" }, "target_language": "es" },
  { "source_language": "en", "word": "apple", "character_grid": [["\u00fa", "k", "\u00fc", "b", "\u00ed", "n", "z", "d", "o"], ["u", "\u00e1", "n", "g", "e", "y", "z", "o", "\u00f1"], ["o", "\u00e9", "\u00fa", "\u00e1", "v", "e", "x", "u", "m"], ["c", "w", "d", "z", "t", "k", "m", "l", "a"], ["u", "b", "o", "w", "\u00ed", "a", "u", "q", "n"], ["g", "s", "m", "e", "c", "n", "k", "\u00fa", "z"], ["a", "o", "v", "t", "p", "\u00fa", "\u00e9", "k", "a"], ["f", "j", "i", "j", "n", "i", "b", "\u00f3", "n"], ["s", "q", "l", "j", "j", "f", "q", "g", "a"]], "word_locations": { "8,2,8,3,8,4,8,5,8,6,8,7,8,8": "manzana" }, "target_language": "es" },
  { "source_language": "en", "word": "eat", "character_grid": [["i", "a", "c", "j", "r", "w"], ["k", "b", "n", "o", "u", "v"], ["v", "x", "z", "f", "m", "a"], ["u", "l", "o", "p", "e", "o"], ["l", "\u00fa", "\u00e9", "q", "j", "e"], ["a", "h", "\u00fa", "l", "k", "w"]], "word_locations": { "2,0,3,1,4,2,5,3": "como" }, "target_language": "es" },
  { "source_language": "en", "word": "bread", "character_grid": [["\u00fc", "\u00e1", "p", "a", "n"], ["k", "a", "k", "m", "l"], ["a", "x", "q", "e", "h"], ["p", "s", "a", "j", "\u00ed"], ["\u00e1", "q", "l", "j", "l"]], "word_locations": { "2,0,3,0,4,0": "pan" }, "target_language": "es" }
];

const gridDataInUse = gridData[0];

const selectedLetters = [{x: 6, y: 1, l: "h"}, {x: 6, y: 2, l: "o"}, {x: 6, y: 3, l: "m"}, {x: 6, y: 4, l: "b"}, {x: 6, y: 5, l: "r"}, {x: 6, y: 6, l: "e"}]

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

you can check the below link that by providing type it is not compaling

Working Code Without Error

CodePudding user response:

Your JSON is structured incorrectly. You are missing some curly brackets, try this...

const data = [
          { names: { "1,2": "Matthew" }},
          { names: { "2,3": "Marcus", "3,4": "Bill" }},
          { names: { "4,5": "Joana", "5,6": "Bob" }}
         ];

JSFiddle: https://jsfiddle.net/j6Lcv9pa/

  • Related