我是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);
});
});
});
下面是我写的函数:
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返回的数据示例如下:
[[1622073600000,"39241.92000000","40411.14000000","37134.27000000","38529.98000000","86547.15879400",1622159999999,"3361413526.05354346",2102182,"42256.01280100","1641681553.52913720","0"],...]
到目前为止,我的单元测试通过了,一切看起来都很好。然后,我尝试通过以下方式在我的应用程序中使用它:
// 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编译器时遇到了以下编译错误:
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
函数中构造对象的方式是不安全的,但是我不确定该怎么做才能解决我的问题。
请在下面找到一个可重现的最小示例
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;
});
}
发布于 2021-06-01 03:11:06
在@jcalz的帮助下,我自己也进行了更多的调试,我已经成功地编译了它。在调用axios get函数时,我需要设置泛型类型:
const result = await axiosGet<any[][]>(`https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1d`);
然后我只需要给我的对象一个提示,在那里我动态地设置了它的属性,它的键类型是一个字符串:
let object: {[index: string]: any} = {};
https://stackoverflow.com/questions/67776863
复制相似问题