Creating a function in Typescript that transforms an array into a typed object

Recently, I have started learning TypeScript and I am working on a function to convert arrays from a web request response into objects. I have successfully written the function along with a passing unit test:

import { parseDataToObject } from './ParseResults';

interface ITestPerson {
  name: string;
  age: number;
}

describe('parseDataToObject', () => {
  // Test cases omitted for simplicity

  describe('passed data and keys array', () => {
    it('returns an array of converted objects matching an interface', () => {
      const testData = [['matt', 25], ['dom', 45]];
      const testKeys = ['name', 'age'];
      const expectToBe: Array<ITestPerson> = [{ name: 'matt', age: 25 }, { name: 'dom', age: 45 }];
      expect(parseDataToObject<ITestPerson>({ data: testData, keys: testKeys })).toStrictEqual(expectToBe);
    });
  });
});

Here is the function that I have implemented:

export function parseDataToObject<T>({ data, keys }: {data: any[][], keys: Array<string>}): Array<T> {
  if (data.length === 0) return [];
  if (data[0].length !== keys.length) throw new Error("Keys array length doesn't match the data count");
  return data.map((dataArr: Array<any>): T => {
    let object = {};
    for (let i = 0; i < keys.length; i++) {
      object[keys[i]] = dataArr[i];
    }
    return object;
  });
}
// The above code resides in ParseResults.ts

Even though the function works fine in jest tests, I'm encountering some TypeScript compilation errors related to type handling.

The main objective is to convert an array of arrays into typed objects. An example of the API response data structure I am dealing with looks like this:

[[1622073600000,"39241.92000000","40411.14000000","37134.27000000","38529.98000000","86547.15879400",1622159999999,"3361413526.05354346",2102182,"42256.01280100","1641681553.52913720","0"],...]

After successful testing, when I try to implement it in my application as shown below:

// Binance.ts
export interface IKlineData {
  openTime: number;
  open: string;
  high: string;
  low: string
  close: string;
  volume: string;
  closeTiime: number;
  quoteAssetVol: string;
  numTrades: number;
  takerBuyBaseAssetVol: string;
  takerBuyQuoteAssetVol: string;
  ignore: string;
}
const klineDataKeys = [
  'openTime',
  'open',
  'high',
  'low',
  'close',
  'volume',
  'closeTiime',
  'quoteAssetVol',
  'numTrades',
  'takerBuyBaseAssetVol',
  'takerBuyQuoteAssetVol',
  'ignore'];


const result = await axiosGet(`https://api.binance.com/api/v3/klines?symbol=${symbol}&interval=1d`);
// Line 68 
const klineData: Array<IKlineData> = parseDataToObject<IKlineData>({data: result.data, keys: klineDataKeys});

Unfortunately, TypeScript compiler throws a few errors as follows:

src/index.d/Binance.ts(68,75): error TS2322: Type 'unknown' is not assignable to ty
pe 'any[][]'.
src/index.d/binance.d/ParseResults.ts(7,7): error TS7053: Element implicitly has an
 'any' type because expression of type 'string' can't be used to index type '{}'.
  No index signature with a parameter of type 'string' was found on type '{}'.
src/index.d/binance.d/ParseResults.ts(9,5): error TS2322: Type '{}' is not assignab
le to type 'T'.
  'T' could be instantiated with an arbitrary type which could be unrelated to '{}'

I understand that there might be some unsafe operations within the parseDataToObject function, but I'm unsure how to rectify these issues. Any help would be greatly appreciated.

Below is a minimal reproducible example for reference:

import axios, { AxiosRequestConfig } from 'axios';

export interface IResponseData<T> {
  status: number;
  data: T;
}

export interface IKlineData {
  openTime: number;
  open: string;
  high: string;
  low: string
  close: string;
  volume: string;
  closeTiime: number;
  quoteAssetVol: string;
  numTrades: number;
  takerBuyBaseAssetVol: string;
  takerBuyQuoteAssetVol: string;
  ignore: string;
}
const klineDataKeys = [
  'openTime',
  'open',
  'high',
  'low',
  'close',
  'volume',
  'closeTiime',
  'quoteAssetVol',
  'numTrades',
  'takerBuyBaseAssetVol',
  'takerBuyQuoteAssetVol',
  'ignore'];

function axiosGet<T>(url: string): Promise<IResponseData<T>> {
  const axiosConfig: AxiosRequestConfig = {
    method: 'get',
    url,
    headers: {
      'Content-Type': 'application/json',
    },
  };

  return new Promise<IResponseData<T>>((resolve, reject) => axios(axiosConfig)
    .then((response) => {
      resolve({ data: response.data, status: response.status });
    })
    .catch((error) => {
      reject(error);
    }));
}

(async function () {
    const result = await axiosGet(`https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1d`);
    const klineData: Array<IKlineData> = parseDataToObject<IKlineData>({data: result.data, keys: klineDataKeys});
}());


function parseDataToObject<T>({ data, keys }: {data: any[][], keys: Array<string>}): Array<T> {
  if (data.length === 0) return [];
  if (data[0].length !== keys.length) throw new Error("Keys array length doesn't match the data count");
  return data.map((dataArr: Array<any>): T => {
    let object = {};
    for (let i = 0; i < keys.length; i++) {
      object[keys[i]] = dataArr[i];
    }
    return <T>object;
  });
}

Answer №1

Thanks to the assistance from @jcalz and a bit of additional troubleshooting on my end, I successfully resolved the issue and got it to compile. It was necessary for me to specify the generic type when calling the axios get function:

const response = await axiosGet<any[][]>(`https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1d`);

Furthermore, I had to provide explicit typing for the object where I dynamically define its properties as strings:

let obj: {[key: string]: any} = {};

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

Retrieve unique values based on two or more criteria from an array in TypeScript

Presented here is an array. https://i.stack.imgur.com/zHXim.png The desired pattern is: https://i.stack.imgur.com/EGUiM.png I am interested in retrieving unique "CityRef" and "City". Subsequently, locating all items associated with them. ...

The type 'elementfinder' cannot be assigned to a parameter of type 'boolean'

Currently, I am working on a function that checks if a checkbox is selected. If it's not checked, then the function should click on it. However, I encountered an error message stating "argument of type 'elementfinder' is not assignable to pa ...

Leveraging Typescript's robust type system to develop highly specific filter functions

I'm attempting to utilize the robust TypeScript type system in order to construct a highly typed 'filter' function that works on a collection (not just a simple array). Below is an illustration of what I am striving for: type ClassNames = &a ...

Enhance your UI experience with a beautifully styled button using Material-

I was using a Material UI button with a purple background. <Button component={Link} to={link} style={{ background: '#6c74cc', borderRadius: 3, border: 0, color: 'white', heig ...

Regex struggles to identify words containing foreign characters

Here is a method I have created to check if a user-input term matches any blacklisted terms: static checkAgainstBlacklist(blacklistTerms, term) { return blacklistTerms.some(word => (new RegExp(`\\b${word}\\b`, 'i&ap ...

Is there a way to align all child elements to the right side inside a multi-select checkbox dropdown list using Angular?

I am seeking assistance with the following scenarios: I have a multiselect dropdownlist using the ng-multiselect-dropdown control in Angular. The parent and child items are bound using the code below in the HTML file: <ng-multiselect-dropdown name=&qu ...

Exploring the potential of Socket.io and Angular with the seamless integration of

I have encountered an issue regarding the use of async pipe with Observables. Initially, I assumed that returning an Observable from my service on a socket.on event would suffice. However, it appears that my approach is incorrect. Can you guide me on the c ...

Apologies, but it seems there was an issue with the installation of the "@angular/compiler-cli" package

Despite thoroughly searching through various threads, I am still unable to find a solution to my problem. I have cloned the angular2 quickstart project and ensured that all module versions are up to date. For reference, here is the link to the repository ...

Exploring Angular Unit Testing: A Beginner's Guide to Running a Simple Test

I'm diving into the world of angular unit testing and looking to set up my first successful test. Here's what I've come up with: import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { AppComponent } fro ...

What is the reason behind Typescript executing the abstract class before anything else?

I'm currently facing a challenge solving an abstract class problem with Typescript. Let me explain what I am trying to accomplish. There is a class named Sword that extends Weapon. Each Weapon must have certain properties like the damage, but since e ...

How should JSON files stored on the server side be properly utilized in Next.js?

Currently, I have a collection of JSON files that I expose through an API endpoint on my web application for global access. This allows different parts of the application to retrieve the data by sending a fetch request to itself... However, since this inf ...

Is it possible to exclude a certain prop from a styled component that has emotions?

Within my code, there exists a component called BoxWithAs, which is defined as follows: const BoxWithAs = styled.div( { WebkitFontSmoothing: 'antialiased', MozOsxFontSmoothing: 'grayscale' // And more … } ); Everythin ...

Error encountered during conversion from JavaScript to TypeScript

I am currently in the process of converting JavaScript to TypeScript and I've encountered the following error: Type '(props: PropsWithChildren) => (any[] | ((e: any) => void))[]' is not assignable to type 'FC'. Type '(a ...

What is the proper way to validate a property name against its corresponding value?

Here is the structure of my User class: export class User { public id: number; //Basic information public email: string; public firstName: string; public lastName: string; //Permissions public canHangSocks: boolean; p ...

Assign a predetermined value to a dropdown list within a FormGroup

I have received 2 sets of data from my API: { "content": [{ "id": 1, "roleName": "admin", }, { "id": 2, "roleName": "user", }, { "id": 3, "roleName": "other", } ], "last": true, "totalEleme ...

Extracting an array from an HTTP response in Angular/Typescript using the map operator or retrieving a specific element

Q1: How can I extract an array of objects from a http response using map in Angular? Q2: Is there a way to retrieve a specific object from a http response by utilizing map in Angular? Below are the example URL, sample data, CurrencyAPIResponse, and Curre ...

Is it possible to verify or authenticate the properties received directly from the associated type or interface?

Looking for a more efficient way to handle validation in my component that takes an array of tabs and children as props. I would like to check if the children provided are the same length as the tabs array directly from the type declaration or any cleaner ...

Is it possible to pass multiple parameters in Angular by utilizing the click() function?

Is there a method for passing parameters with click() in Angular? <a asp-action="CreateSales" (click)="CreateSales(productname='pa', price='16.5')">Some Text</a> I am still learning Angular and would appreciat ...

After successfully logging in, the deployed server encounters an Error 503 and shuts down. However, on the development environment, everything runs smoothly as

I am currently in the process of developing an application using NET 6 LTS and Angular 14. Everything runs smoothly on my development environment with IIS express. However, once I deploy the application (release version) on Windows 2019 with IIS 10, I enco ...

Utilize JavaScript libraries in a TypeScript project

Looking to integrate a payment system called iyzico into my project. The iyzico payment library can be found here. However, there are no types available for it. How can I utilize this library in my Node.js TypeScript Express backend project? I attempted t ...