我想了解打字稿/ JavaScript的格式,并且需要帮助来了解此处的某些步骤。我正在将JSON文件解析为一个对象,然后尝试读取值以更新某些值。
感谢Timmy chan,我从以前的文章中得到了一些建议,现在是在此基础上进行的。 Objects creation using interface for JSON types in typescript
说我已经定义了此接口,
interface AllData {
[value:string]:Row
}
interface Row {
eDate: string;
mystate: string;
mystateCity: string;
numberofpeople: number;
}
let Data: AllData ;
我这样读取文件,并将其分配给Data变量。
const response = await fetchFile(fileName);
Data= await response.json();
现在我要创建一个仅包含行的新对象
const CountData: Row[] = {} // this gives error Type '{}' is missing the following properties from type 'CountyGraphRow[]': length, pop, push,
if I change it to
const CountData: Row[] = [] // when to have {} or [].. What is the difference?
for (const rowData in Data["value"])
{
console.log(rowData); // this is coming out 0
CountData.push({ // error at TypeError: Cannot read property 'eDate' of undefined
eDate: Data[rowData].eDate, // Something is wrong in the way I am accessing them.
mystate: Data[rowData].mystate,
mystateCity: Data[rowData].mystateCity,
numberofpeople: Data[rowData].numberofpeople > 20? 20 : Data[rowData].numberofpeople < 5? 5: Data[rowData].numberofpeople,
})
}
这是文件的外观
{
"value": [
{
"eDate": "2020-03-01T00:00:00.000Z",
"mystate": "state1",
"mystateCity": "state1, ID",
"numberofpeople": 2.973529602
},
{
"eDate": "2020-03-02T00:00:00.000Z",
"mystate": "state1",
"mystateCity": "state1, ID",
"numberofpeople": 2.973529602
},
{
"eDate": "2020-03-03T00:00:00.000Z",
"mystate": "state1",
"mystateCity": "state1, ID",
"numberofpeople": 2.973529602
}
]}
--------------更新2 -------------
interface AllData {
[value: string]: Row
}
interface Row {
eDate: string;
mystate: string;
mystateCity: string;
numberofpeople: number;
}
let Data: AllData;
Data = JSON.parse(`{
"value": [
{
"eDate": "2020-03-01T00:00:00.000Z",
"mystate": "state1",
"mystateCity": "state1, ID",
"numberofpeople": 2.973529602
},
{
"eDate": "2020-03-02T00:00:00.000Z",
"mystate": "state1",
"mystateCity": "state1, ID",
"numberofpeople": 2.973529602
},
{
"eDate": "2020-03-03T00:00:00.000Z",
"mystate": "state1",
"mystateCity": "state1, ID",
"numberofpeople": 2.973529602
}
]}`);
const CountData: Row[] = [];
for (const rowData in Data["value"]) { // Data["value"] I am assuming this //will pick all objects "value": [
// {
// "eDate": "2020-03-01T00:00:00.000Z",
// please correct me if I am wrong
console.log(rowData); // this is coming out 0
CountData.push({ // error at TypeError: Cannot read property 'eDate' of undefined
eDate: Data[rowData].eDate, // Something is wrong in the way I am accessing them.
mystate: Data[rowData].mystate,
mystateCity: Data[rowData].mystateCity,
numberofpeople: Data[rowData].numberofpeople > 20 ? 20 : Data[rowData].numberofpeople < 5 ? 5 : Data[rowData].numberofpeople,
})
}
答案 0 :(得分:4)
哦,{}
与[]
的问题:前者是一个空对象,而后者是一个空数组。在JavaScript中,数组是所有对象,但并非所有对象都是数组。具体来说,数组具有您关心的所有数组方法,例如push()
。如果CountData
应该是数组,则不能为其分配{}
,因为它缺少数组所需的内容。
关注问题的主要部分:
这里的第一个问题是您的界面
interface AllData {
[value:string]:Row
}
具有string index signature,这意味着“ AllData
可以具有任意数量的任何string
值的键,并且每个键的属性将是单个{{ 1}}对象”。
请注意,上面定义中的Row
只是一个占位符,对类型没有任何影响。确切定义与
value
无论如何,您的问题是您正在阅读的interface AllData {
[x:string]:Row
}
没有这种形状。它有一个名称完全为Data
的单个键,该键的属性是"value"
个对象的 array 。含义如下:
Row
修复此问题后,我们来看一下对代码进行的最小更改以使其正常运行,然后从那里进行改进:
let Data: { value: Row[] };
循环const CountData: Row[] = [];
for (const rowData in Data["value"]) {
CountData.push({
eDate: Data["value"][rowData].eDate,
mystate: Data["value"][rowData].mystate,
mystateCity: Data["value"][rowData].mystateCity,
numberofpeople: Data["value"][rowData].numberofpeople > 20 ? 20 :
Data["value"][rowData].numberofpeople < 5 ? 5 :
Data["value"][rowData].numberofpeople,
})
}
遍历for (const rowData in Data["value"])
数组的键。这些将是与数组索引相对应的字符串值:Data["value"]
,"0"
,"1"
等。通常not recommended通过{{1 }},因为您将获得索引作为字符串,可能是乱序的,并且其中可能还有其他意外内容。尽管如此,它还是可以的。
尽管如此,这里的主要问题是:由于您要遍历"2"
的键,因此您需要通过索引到for..in
而不是Data["value"]
来读取其属性。
让我们停止使用Data["value"]
遍历数组索引,并使用常规的for循环:
Data
现在可以保证顺序发生,并且没有任何奇怪的非数字索引。
下一个改进:让我们停止说for..of
,因为没有理由将括号属性访问与有效的JavaScript标识符的字符串文字一起使用。您可以只使用const CountData: Row[] = [];
for (let i = 0; i < Data["value"].length; i++) {
CountData.push({
eDate: Data["value"][i].eDate,
mystate: Data["value"][i].mystate,
mystateCity: Data["value"][i].mystateCity,
numberofpeople: Data["value"][i].numberofpeople > 20 ? 20 :
Data["value"][i].numberofpeople < 5 ? 5 : Data["value"][i].numberofpeople,
})
}
。
另外,不要将Data["value"]
写很多次,只需将其保存到自己的变量中(嘿,我们现在可以将其称为Data.value
):
Data.value[i]
接下来,您可以考虑使用for...of
循环直接迭代rowData
元素,而不必关心其数字索引 :
const CountData: Row[] = [];
for (let i = 0; i < Data.value.length; i++) {
const rowData = Data.value[i];
CountData.push({
eDate: rowData.eDate,
mystate: rowData.mystate,
mystateCity: rowData.mystateCity,
numberofpeople: rowData.numberofpeople > 20 ? 20 :
rowData.numberofpeople < 5 ? 5 : rowData.numberofpeople,
})
}
}
接下来,复制单个属性很好,但是如果要复制所有或大多数属性,则可以使用object literal spread syntax快速完成(或类似的Object.assign()
),然后只需重写要更改的一个属性即可:
rowData
}
最后,如果您要做的只是遍历一个数组并生成大小完全相同的另一个数组,而输入中的每个元素在输出中生成单个元素,则可以省去循环和const CountData: Row[] = [];
for (const rowData of Data.value) {
CountData.push({
eDate: rowData.eDate,
mystate: rowData.mystate,
mystateCity: rowData.mystateCity,
numberofpeople: rowData.numberofpeople > 20 ? 20 :
rowData.numberofpeople < 5 ? 5 :
rowData.numberofpeople,
});
}
完全使用并改为使用Array.prototype.map()
:
const CountData: Row[] = [];
for (const rowData of Data.value) {
CountData.push({
...rowData,
numberofpeople: rowData.numberofpeople > 20 ? 20 :
rowData.numberofpeople < 5 ? 5 : rowData.numberofpeople
})
}
}
哇!我认为这是我所能做到的。