【问题标题】:Define Object type with variable properties name in TypeScript在 TypeScript 中使用变量属性名称定义对象类型
【发布时间】:2018-12-13 09:08:27
【问题描述】:

我正在为 React + TypeScript 的“问题”而苦苦挣扎:它实际上并没有停止我的应用程序,但现在我想消除这个疑问!.. 这更像是一个问题!

我想要实现的是定义对象的属性名称,而属性名称由变量给出。让我用一个例子来解释 -> https://codepen.io/Gesma94/pen/xmwMzY

/* The 'data' property is "dynamic": it will always have this structure,
 * but the name properties (and the values) may change.
 * The 'mapping' property is used to know the name properties inside 'data'.
 */  
const series = {
  data: [
    {map1: "People reached", map2: 200},
    {map1: "People who called", map2: 117},
    {map1: "Contract signed", map2: 77}
  ],
  mapping: {
    stage: "map1",
    values: "map2"
  }
};

/* This is the actual app. */
const myPar = document.getElementById("myPar");
const { stage: stageLabel, values: valuesLabel} = series.mapping;

series.data.forEach((sample: any, index: number) => {
  myPar.innerHTML = myPar.innerHTML + "<br>" + sample[stageLabel];
});

如您所见,在forEach 我写sample: any

现在,我知道sample 有一个名为map1string(第一个永远是string)属性,这是因为我检索并保存在stageLabel 中。我也知道另一个属性是number(它总是number),它的名字map2保存在valueLabel中。

现在,我急需了解的是如何不写sample: any,而是使用我之前检索到的信息定义sample 的类型。 基本上,我想写类似:sample: {stageLabel: string, valueLabel: number},但这样做 TypeScript 相信sample 具有属性stageLabelvalueLabel,因为我们处于“编译时间”并且它甚至无法评估变量。

所以,由于 TypeScript 无法知道变量中的内容,我知道我实际上无法获得 sample: {map1: string, map2: number},但也许我可以获得某种别名。 例如,我写sample: {stageLabel: string, valueLabel: number},在其余代码中我使用属性sample.stageLabelsample.valueLabel。然后,当应用程序运行时,会评估这些属性名称,因此 sample.stageLabel 实际上是 sample.map1

我希望我已经足够清楚地理解我的问题。

【问题讨论】:

    标签: javascript typescript


    【解决方案1】:

    为什么不实际映射您的数据?

    const series = {
      data: [
        {map1: "People reached", map2: 200},
        {map1: "People who called", map2: 117},
        {map1: "Contract signed", map2: 77}
      ],
      mapping: {
        stage: "map1",
        values: "map2"
      }
    };    
    
    const myPar = document.getElementById("myPar");
    
    let mappedData = getMappedData(series.data, series.mapping);
    
    // append results
    mappedData.forEach((record:{stage:string, value:number}) => {
      myPar.innerHTML = myPar.innerHTML + `<br>${record.stage}: ${record.value}`;
    });
    
    
    function getMappedData(data, mapping): {stage:string, value:number}[] {
        let stageLabel = mapping["stage"];
        let valueLabel = mapping["values"];
    
        return data.map(x => {        
            return { stage: x[stageLabel], value: x[valueLabel] };
        })
    }
    &lt;p id="myPar"&gt;&lt;b&gt;Results:&lt;/b&gt;&lt;/p&gt;

    请注意,编译器现在已经知道 mappedData 中的项目具有 {stage:string, value:number} 类型,因此您可以在追加时省略它并简单地编写:

    // append results
    mappedData.forEach(record => {
      myPar.innerHTML = myPar.innerHTML + `<br>${record.stage}: ${record.value}`;
    });
    

    【讨论】:

    • 我想这会起作用:我将使用 TypeScript 检查映射数据,所以谢谢。不过,我想知道我所说的(某种别名)在 TypeScript 中是否可行。如果没有人可以给我答案,我会将您的答案标记为正确。再次感谢:)
    猜你喜欢
    • 2020-03-17
    • 2022-11-03
    • 2011-11-29
    • 2021-07-07
    • 2020-04-14
    • 2015-02-05
    • 1970-01-01
    • 2012-11-04
    • 1970-01-01
    相关资源
    最近更新 更多