了解打字稿界面

时间:2020-10-21 19:06:17

标签: javascript json typescript

我想了解打字稿/ 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,
    })
}

1 个答案:

答案 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
    })
}

}


哇!我认为这是我所能做到的。

Playground link to code