Is there a way for me to loop through an object without prior knowledge of its keys?

Upon receiving data from the server, it looks something like this:

{
  "2021-10-13": {
    "1. open": "141.2350",
    "2. high": "141.4000",
    "3. low": "139.2000",
    "4. close": "140.9100",
    "5. volume": "78762721"
  },
  "2021-10-12": {
    "1. open": "143.2300",
    "2. high": "143.2500",
    "3. low": "141.0401",
    "4. close": "141.5100",
    "5. volume": "73035859"
  },
  "2021-10-11": {
    "1. open": "142.2700",
    "2. high": "144.8100",
    "3. low": "141.8100",
    "4. close": "142.8100",
    "5. volume": "64452219"
  }
}

The key values may not be consistent across different requests. How can I iterate through an object with unknown keys?

For instance, I wish to store the second and third nested objects (stocks) in a database, but I am uncertain about how to specify them. Any suggestions?

Answer №1

Here's a method to interpret the information you're getting and arrange it in descending order based on the newest date:

TS Playground

const rawSummaryKeys = ['1. open', '2. high', '3. low', '4. close', '5. volume'] as const;
type RawSummaryKey = typeof rawSummaryKeys[number];

const parsedSummaryKeys = ['open', 'high', 'low', 'close', 'volume'] as const;
type ParsedSummaryKey = typeof parsedSummaryKeys[number];

const rawToParsedSummaryKeyMapping: Record<RawSummaryKey, ParsedSummaryKey> = {
  '1. open': 'open',
  '2. high': 'high',
  '3. low': 'low',
  '4. close': 'close',
  '5. volume': 'volume',
};

/** Values are parsable as numbers */
type RawSummary = Record<RawSummaryKey, string>;

/** Keys are dates in format: YYYY-MM-DD */
type DailyRawSummaries = Record<string, RawSummary>;

type ParsedSummary = Record<ParsedSummaryKey, number>;

function parseRawSummary (summary: RawSummary): ParsedSummary {
  const parsed = {} as ParsedSummary;
  for (const key of rawSummaryKeys) {
    // If the "volume" number ever exceeds Number.MAX_SAFE_INTEGER,
    // then you can switch to using BigInts
    parsed[rawToParsedSummaryKeyMapping[key]] = Number(summary[key]);
  }
  return parsed;
}

type DailySummaryEntrry = [date: string, summary: ParsedSummary];

function parseDailySummaries (summaries: DailyRawSummaries): DailySummaryEntrry[] {
  const entries: DailySummaryEntrry[] = [];

  for (const date in summaries) {
    const rawSummary = summaries[date];
    if (!rawSummary) continue;
    entries.push([date, parseRawSummary(rawSummary)]);
  }

  return entries.sort().reverse(); // sort by newest date first
}

function main () {
  const json = `{"2021-10-13":{"1. open":"141.2350","2. high":"141.4000","3. low":"139.2000","4. close":"140.9100","5. volume":"78762721"},"2021-10-12":{"1. open":"143.2300","2. high":"143.2500","3. low":"141.0401","4. close":"141.5100","5. volume":"73035859"},"2021-10-11":{"1. open":"142.2700","2. high":"144.8100","3. low":"141.8100","4. close":"142.8100","5. volume":"64452219"}}`;
  const raw: DailyRawSummaries = JSON.parse(json);

  const parsed = parseDailySummaries(raw);

  for (const [date, summary] of parsed) {
    console.log(date, summary);
  }
}

main();

Transpiled JS from TS playground:

const rawSummaryKeys = ['1. open', '2. high', '3. low', '4. close', '5. volume'];
const parsedSummaryKeys = ['open', 'high', 'low', 'close', 'volume'];
const rawToParsedSummaryKeyMapping = {
    '1. open': 'open',
    '2. high': 'high',
    '3. low': 'low',
    '4. close': 'close',
    '5. volume': 'volume',
};
function parseRawSummary(summary) {
    const parsed = {};
    for (const key of rawSummaryKeys) {
        // If the "volume" number ever exceeds Number.MAX_SAFE_INTEGER,
        // then you can switch to using BigInts
        parsed[rawToParsedSummaryKeyMapping[key]] = Number(summary[key]);
    }
    return parsed;
}
function parseDailySummaries(summaries) {
    const entries = [];
    for (const date in summaries) {
        const rawSummary = summaries[date];
        if (!rawSummary)
            continue;
        entries.push([date, parseRawSummary(rawSummary)]);
    }
    return entries.sort().reverse(); // sort by newest date first
}
function main() {
    const json = `{"2021-10-13":{"1. open":"141.2350","2. high":"141.4000","3. low":"139.2000","4. close":"140.9100","5. volume":"78762721"},"2021-10-12":{"1. open":"143.2300","2. high":"143.2500","3. low":"141.0401","4. close":"141.5100","5. volume":"73035859"},"2021-10-11":{"1. open":"142.2700","2. high":"144.8100","3. low":"141.8100","4. close":"142.8100","5. volume":"64452219"}}`;
    const raw = JSON.parse(json);
    const parsed = parseDailySummaries(raw);
    for (const [date, summary] of parsed) {
        console.log(date, summary);
    }
}
main();

Answer №2

Is this information useful?

type Properties = {
  "1. start": string;
  "2. end": string;
  "3. low point": string;
  "4. final value": string;
  "5. trading volume": string;
}
type Data = {[Key in keyof Properties]: Properties[Key]}
type Set = { [identifier: string]: Data}
const output: Set = {
  "2021-10-13": {
    "1. start": "141.2350",
    "2. end": "141.4000",
    "3. low point": "139.2000",
    "4. final value": "140.9100",
    "5. trading volume": "78762721"
  },
  "2021-10-12": {
    "1. start": "143.2300",
    "2. end": "143.2500",
    "3. low point": "141.0401",
    "4. final value": "141.5100",
    "5. trading volume": "73035859"
  },
  "2021-10-11": {
    "1. start": "142.2700",
    "2. end": "144.8100",
    "3. low point": "141.8100",
    "4. final value": "142.8100",
    "5. trading volume": "64452219"
  }
};

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

Deleting a button from a list item or array in Angular 12

Having some trouble removing a list item with the click button, I've tried a few options but nothing seems to be working. Can anyone offer assistance? I need to remove a list item from my users array when clicked. Below is the Typescript code and cor ...

How to extract multiple literals from a string using Typescript

type Extracted<T> = T extends `${string}${'*('}${infer A}${')+'}${string}${'*('}${infer A}${')+'}${string}` ? A : never type Result1 = Extracted<'g*(a12)+gggggg*(h23)+'> // 'a12' | &a ...

Using TypeScript to transform types: Array of objects with keys Kn and values Vn to an object with keys Kn and values Vn

I am looking to create a function that can process tuples with a specific structure like so: type Input = [ { key: K1, value: V1 }, { key: K2, value: V2 }, { key: K3, value: V3 }, // ... { key: KN, value: VN } ] The function should then output ...

Can you identify the specific function type passed through props?

interface IProps { handleCloseModal: React.MouseEventHandler<HTMLButtonElement> returnFunction: () => void; } export default function Modal({ children, returnFunction, handleCloseModal, }: React.PropsWithChildren<IProps>) { cons ...

Karma Unit test: Issue with accessing the 'length' property of an undefined value has been encountered

While running karma unit tests, I encountered a similar issue and here is what I found: One of my unit tests was writing data to a json file, resulting in the following error: ERROR in TypeError: Cannot read property 'length' of undefined a ...

Tips for utilizing the "??=" syntax in Typescript

let x; x ??= 'abc' console.log(x); // abc Running the code above in the browser console does not cause any issues. However, when attempting to run it in TypeScript, an error is thrown. SyntaxError: Unexpected token '??=' Here is my c ...

What is the most efficient way to convert a JSON object into a URL search parameter using as few characters as possible?

Challenge: On my web app, users can adjust settings to create or edit generative artworks and then share their creations via a shortened link. The objective is to store all the data needed to replicate the artwork in the URL within 280 characters. Initia ...

I am experiencing issues with my Angular2 project where not all of my component variables are being passed to the

My problem involves sending three variables to my HTML template, but it only recognizes one of them. The HTML template I am using looks like this: <div class="page-data"> <form method="post" action="api/roles/edit/{{role?.ID}}" name="{{role? ...

Utilize cypress to analyze the loading time of a webpage

My current challenge involves using cypress to carry out website tests. I am looking for a reliable method to measure the duration it takes for certain cypress commands to load or execute. As an example: //var startTime = SomeStopwatchFunction(); cy.visit( ...

Python Hangman - Iterations

I've been trying to create a function for playing hangman which is almost perfect except for one tiny hiccup - it doesn't recognize when the game has been successfully won. ---UPDATE--- Check out my revised code below: def play_hangman(): ...

The component prop of Typography in TypeScript does not accept MUI styling

Working with MUI in typescript and attempting to utilize styled from MUI. Encountering an error when passing the component prop to the styled component. The typescript sandbox below displays the issue - any suggestions for a workaround? https://codesandbo ...

Preventing Redundancy in Angular 2: Tips for Avoiding Duplicate Methods

Is there a way I can streamline my if/else statement to avoid code repetition in my header component? Take a look at the example below: export class HeaderMainComponent { logoAlt = 'We Craft beautiful websites'; // Logo alt and title texts @Vie ...

I am attempting to incorporate an NPM package as a plugin in my Next.js application in order to prevent the occurrence of a "Module not found: Can't resolve 'child_process'" error

While I have developed nuxt apps in the past, I am new to next.js apps. In my current next.js project, I am encountering difficulties with implementing 'google-auth-library' within a component. Below is the code snippet for the troublesome compon ...

Angular's HttpClient makes sure to wait for the HTTP requests to complete

Initializing arrays with the call this.Reload.All() is causing confusion and breaking the service due to multiple asynchronous calls. I am looking for a synchronous solution where each call waits for its response before proceeding to the next one. How can ...

What steps can be taken to resolve the issue of being unable to rename an element in Typescript?

Why does VS code editor sometimes prevent me from renaming my typescript symbol using the f2 key? I keep encountering the error message "This element cannot be renamed." https://i.stack.imgur.com/mmqu9.png In some of my other projects, I am able to renam ...

What is the reason for the index type being defined twice?

Here is an example from the official TypeScript documentation: class Animal { name: string; } class Dog extends Animal { breed: string; } // Error: indexing with a 'string' will sometimes get you a Dog! interface NotOkay { [x: numbe ...

What is the best way to refresh NGRX data?

There are two models in a one-to-many relationship: export interface GroupModel { id: number; name: string; userIds?: number[]; } export interface UserModel { id: number; name: string; groupId?: number; } An issue arises when updating either m ...

What is the best way to show all cards in Angular when no filtering input is provided?

I have implemented a filter feature for multiple cards in Angular using Pipes. The filter works well, but I am facing an issue where no cards are displayed when there is no input value provided. I would like all the cards to be displayed when no input is g ...

Even when using module.exports, NodeJS and MongoDB are still experiencing issues with variable definitions slipping away

Hello there, I'm currently facing an issue where I am trying to retrieve partner names from my MongoDB database and assign them to variables within a list. However, when I attempt to export this information, it seems to lose its definition. Can anyone ...

The type string[] cannot be assigned to type 'IntrinsicAttributes & string[]'

I'm attempting to pass the prop of todos just like in this codesandbox, but encountering an error: Type '{ todos: string[]; }' is not assignable to type 'IntrinsicAttributes & string[]'. Property 'todos' does not ex ...