[英]Understanding typescript interfaces
我想了解 typescript/javascript 的格式,并且需要帮助来理解此处的某些步骤。 我正在将 JSON 文件解析为一个对象,然后尝试读取值以更新某些值。
感谢 Timmy chan,我从我之前的帖子中得到了一些建议,现在以此为基础。 使用打字稿中 JSON 类型的接口创建对象
假设我定义了这个接口,
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,
})
}
哦, {}
与[]
:前者是一个空对象,后者是一个空数组。 在 JavaScript 中,数组都是对象,但并非所有对象都是数组。 具体来说,数组具有您关心的所有数组方法,例如push()
。 如果CountData
应该是一个数组,则不能为其分配{}
,因为它缺少数组所需的东西。
继续你的问题的主要部分:
这里的第一个问题是你的界面
interface AllData {
[value:string]:Row
}
有一个字符串索引签名,这意味着“一个AllData
可以有任意数量的任意string
值的键,并且每个键的属性将是一个Row
对象”。
请注意,上述定义中的value
只是一个占位符,对类型没有任何影响。 它与完全相同的定义
interface AllData {
[x:string]:Row
}
无论如何,您的问题是您正在阅读的Data
没有那种形状。 它具有完全相同的名称的单个键"value"
,并在该键的属性是一个数组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"
、 "2"
等。通常不建议通过for..in
迭代数组,因为您将获得索引作为字符串,可能是乱序的,并且可能有其他意想不到的东西。 不过,它有点工作。
不过,这里的主要问题是:由于您正在迭代Data["value"]
的键,您需要通过索引到Data["value"]
而不是Data
来读取其属性。
让我们停止使用for..of
迭代数组索引并使用常规 for 循环:
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"]
因为没有理由使用括号属性访问和字符串文字是有效的 JavaScript 标识符。 您可以只使用Data.value
。
此外,不要多次写入Data.value[i]
,只需将其保存到自己的变量中(嘿,我们现在可以调用该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,
})
}
接下来,您可以考虑使用for...of
循环直接迭代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,
});
}
}
接下来,复制单个属性很好,但是如果您要复制所有或大部分属性,您可以使用对象字面量扩展语法来快速完成(或Object.assign()
类似),然后只需重写您要更改的一项属性:
const CountData: Row[] = [];
for (const rowData of Data.value) {
CountData.push({
...rowData,
numberofpeople: rowData.numberofpeople > 20 ? 20 :
rowData.numberofpeople < 5 ? 5 : rowData.numberofpeople
})
}
}
最后,如果您所做的只是遍历一个数组并生成另一个大小完全相同的数组,其中输入中的每个元素在输出中生成一个元素,则您可以完全省去循环和push
并使用Array.prototype.map()
代替:
const CountData = Data.value.map(rowData => ({
...rowData,
numberofpeople: rowData.numberofpeople > 20 ? 20 :
rowData.numberofpeople < 5 ? 5 : rowData.numberofpeople
}));
}
哇! 我认为这是我能做到的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.