Home > Mobile >  Typecast variable to extract of nested data
Typecast variable to extract of nested data

Time:06-03

I'm receiving an array of nested objects from an API call from which I need to extract information and bundle it to be able to display it in a table. I'm using for (const [key, value] of Object.entries(result)) for looping through the results. My code works fine but gives me an error on yarn build on the step where I'm trying to extract nested objects from the value. I'm currently doing this by using the dot notation as value.property. Sample code :

const result = await HTTPService.get(`myEndpoint/v1`);
for (const [key, value] of Object.entries(result)) {
     name = key;
     if (value.property1) {
         myVar = value.myProperty1.subProperty1;
     }
}

Error: Property 'myProperty1' does not exist on type 'value'

result (response from the API call) looks something like this:

{
  name1: {
     myProperty1: {
         subProperty1: []
         subProperty2: {}
        }
     myProperty2: {}
  }
}

CodePudding user response:

If you can guarantee that the response is going to be of that shape, you could typecast it using as keyword. You could create a custom type of the shape of the response you get (you can probably just put any for any of the sub properties you don't care about, or just completely ignore them) and typecast it using that type.

type MyResType = {
  name1: {
     myProperty1: {
         subProperty1: something[]
         subProperty2: {...}
        }
     myProperty2: {...}
  }
}

const result = await HTTPService.get(`myEndpoint/v1`);

for (const [key, value] of Object.entries(result as MyResType)) {
     name = key;
     if (value.property1) {
         myVar = value.myProperty1.subProperty1;
     }
}

CodePudding user response:

Using Optional Chain

You can use optional chain to avoid that type checking error.

for (const [key, value] of Object.entries(result as MyResType)) {
     name = key;
     if (value?.property1) {
         myVar = value.myProperty1.subProperty1;
     }
}

Add Response Type

As the response from the API is unknown on side of frontend. And you could add the type checking for the response.

If you are sure about the response type, you can define it's response's type.

type ResultType = {
  name1: {
     myProperty1: {
         subProperty1: Array<any>
         subProperty2: {}
     }
     myProperty2: {}
  }
}

const result = await HTTPService.get<ResultType>(`myEndpoint/v1`);

CodePudding user response:

For TypeScript to detect that value's type is the type of name1, you need to check if (key === 'name1'). In the context of this if, TypeScript will know that key's type is "name1", and then it can infer the type of result[key].

interface Result {
  name1: {
     myProperty1: {
       subProperty1: [];
       subProperty2: {};
     };
     myProperty2: {};
  };
}

const result = await HTTPService.get(`myEndpoint/v1`) as Result;

for (const key of Object.keys(result) as Array<keyof Result>) {
  name = key;

  if (key === 'name1') {
    const typedValue = result[key];
    // works: TS knows that `typedValue`'s type is `{ myProperty1: ..., myProperty2: ... }`
    myVar = typedValue.myProperty1.subProperty1;
  }

  // doesn't work: `key`'s type in this context is `keyof Result` and not specifically `"name1"`
  const untypedValue = result[key];
  myVar = untypedValue.myProperty1.subProperty1;
  //      ~~~~~~~~~~~~ TS2571: Object is of type 'unknown'.
});

See TypeScript playground example.

  • Related