首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在Typescript中创建将数组转换为类型化对象的函数

如何在Typescript中创建将数组转换为类型化对象的函数
EN

Stack Overflow用户
提问于 2021-05-31 23:48:37
回答 1查看 33关注 0票数 0

我是typescript的新手,我正在尝试编写一个函数,可以用来将数组从web请求响应转换为对象。我已经编写了一个函数和一个正在通过的单元测试:

代码语言:javascript
运行
复制
import { parseDataToObject } from './ParseResults';

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

describe('parseDataToObject', () => {
  // Ommitted simple cases such as testing for empty arrays etc...

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

下面是我写的函数:

代码语言:javascript
运行
复制
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;
  });
}
//above is ParseResults.ts

该函数在jest中按预期工作,因此它看起来与JavaScript功能一样有效,但我的问题是额外的typescript类型。

我希望大家都明白,我希望将数据数组的数组转换为类型化的对象数组。我使用的API返回的数据示例如下:

代码语言:javascript
运行
复制
[[1622073600000,"39241.92000000","40411.14000000","37134.27000000","38529.98000000","86547.15879400",1622159999999,"3361413526.05354346",2102182,"42256.01280100","1641681553.52913720","0"],...]

到目前为止,我的单元测试通过了,一切看起来都很好。然后,我尝试通过以下方式在我的应用程序中使用它:

代码语言:javascript
运行
复制
// 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`);
// following is line 68
const klineData: Array<IKlineData> = parseDataToObject<IKlineData>({data: result.data, keys: klineDataKeys});

但我在使用typescript编译器时遇到了以下编译错误:

代码语言:javascript
运行
复制
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 '{}'

我可以看到我在parseDataToObject函数中构造对象的方式是不安全的,但是我不确定该怎么做才能解决我的问题。

请在下面找到一个可重现的最小示例

代码语言:javascript
运行
复制
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;
  });
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-06-01 03:11:06

在@jcalz的帮助下,我自己也进行了更多的调试,我已经成功地编译了它。在调用axios get函数时,我需要设置泛型类型:

代码语言:javascript
运行
复制
const result = await axiosGet<any[][]>(`https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1d`);

然后我只需要给我的对象一个提示,在那里我动态地设置了它的属性,它的键类型是一个字符串:

代码语言:javascript
运行
复制
let object: {[index: string]: any} = {};
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67776863

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档