Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Typescript中创建将数组转换为类型化对象的函数_Typescript_Generics_Typescript Generics - Fatal编程技术网

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

如何在Typescript中创建将数组转换为类型化对象的函数,typescript,generics,typescript-generics,Typescript,Generics,Typescript Generics,我是typescript新手,我正在尝试编写一个函数,可以用来将数组从web请求响应转换为对象。我已经编写了一个函数和一个正在通过的单元测试: import { parseDataToObject } from './ParseResults'; interface ITestPerson { name: string; age: number; } describe('parseDataToObject', () => { // Ommitted simple cases

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

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);
    });
  });
});
到目前为止,通过了单元测试,一切看起来都很好。然后,我尝试通过以下方式在我的应用程序中使用它:

// 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});
我可以看出,我在
parseDataToObject
函数中构造对象的方式是不安全的,但我不确定该如何解决我的问题

请在下面找到一个最小的可复制示例

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;
  });
}
导入axios,{AxiosRequestConfig}来自“axios”;
导出接口IResponda{
状态:编号;
资料:T;
}
导出接口IKlineData{
开放时间:数字;
打开:字符串;
高:字符串;
低:字符串
关闭:字符串;
卷:字符串;
关闭时间:数字;
quoteasetvol:string;
numTrades:数字;
takerBuyBaseAssetVol:字符串;
TakerBuyQuoteAsetVol:string;
忽略:字符串;
}
常数klineDataKeys=[
“开放时间”,
"开放",,
"高",,
“低”,
“结束”,
"卷",,
“关门时间”,
“QuoteAsetVol”,
“numTrades”,
“takerBuyBaseAssetVol”,
“TakerBuyQuoteAsetVol”,
“忽略”];
函数axiosGet(url:string):Promise{
常量axiosConfig:AxiosRequestConfig={
方法:“get”,
网址,
标题:{
“内容类型”:“应用程序/json”,
},
};
返回新承诺((解决、拒绝)=>axios(axiosConfig)
。然后((响应)=>{
解析({data:response.data,status:response.status});
})
.catch((错误)=>{
拒绝(错误);
}));
}
(异步函数(){
常量结果=等待axiosGet(`https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1d`);
const klineData:Array=parseDataToObject({data:result.data,key:klineDataKeys});
}());
函数parseDataToObject({data,key}:{data:any[],key:Array}):数组{
if(data.length==0)返回[];
如果(数据[0].length!==keys.length)抛出新错误(“keys数组长度与数据计数不匹配”);
返回data.map((dataArr:Array):T=>{
让对象={};
for(设i=0;i
在@jcalz的帮助和我自己的调试之后,我成功地将其编译。调用axios get函数时,我需要设置泛型类型:

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

请考虑修改这个问题中的代码,以便构成一个当它落入独立IDE时,清楚地显示出你所面临的问题。这将允许那些想要帮助您的人立即着手解决问题,而无需首先重新创建问题。它将使您得到的任何答案都可以根据定义良好的用例进行测试。@jcalz我已经做了一个,我最好通过编辑原始帖子来分享它吗?那么,当您调用
const result=wait axiosGet(…)
,您希望
result
的类型是什么?您的
axiosGet()
函数在类型参数
T
中是泛型的,但是编译器无法从中推断
T
的类型,对吗?编译器返回到
unknown
,然后在调用
parseDataToObject()
时出现该错误。也许您想调用
等待axiosGet(…)
来抑制错误?坦率地说,我不确定是什么促使您在这里使用泛型,或者这些泛型如何比使用
任何
更好。你能解释一下目的吗?假设我有两个函数,像这样:
declare function foo():any
declare function bar():T
。它们都不是类型安全的,方式非常相似。函数
foo()
是否真的可以返回调用者想要的任何类型的值,而不必告诉
foo
实现关于这种类型的任何信息?您是否应该信任常量x:string=foo()?不,你不应该。函数
bar()
真的可以返回调用者想要的任何类型的值吗?我可以调用
const x=bar()
,但是
bar()
怎么知道它应该返回一个
字符串呢?如果
any
让你质疑TypeScript的有用性,那么任何承诺返回一个泛型类型的值而没有该类型的输入或者与该类型相关的函数也应该如此。类似于
(x:T)=>T
的东西很好(您可以返回输入);类似于
(x:Array)=>T | undefined
的东西是可以的(您可以返回数组中的一个元素),但是
(x:string)=>T
只是凭空神奇地生成了调用方指定的
T
的值。我认为
fetch()
-like代码可能经常是这样的,但它并不比
any
更安全。
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 '{}'
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;
  });
}
const result = await axiosGet<any[][]>(`https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1d`);
let object: {[index: string]: any} = {};