javascript - Typescript , what's the best approach for declaring a nested object with different types? - Stack Overflow

I have this JS object and I want to port it to Typescript:var items = [{style: 'activity-8',c

I have this JS object and I want to port it to Typescript:

var items = [{
      style: 'activity-8',
      color: '#a32c62',
      id:    8,
      done : false,
      label : {
        short :'999 m',
        long  :'walk 999m',
        statstime  :'yesterday'
      },
      val : {
        today : {
          target   : { 
            raw : 0,
            display :"11"
          },
          achieved : {
            raw : 0,
            display :"22"
          }
        },
        yesterday : {
          target   : {
            raw : 0,
            display :"33"
          },
          achieved : {
            raw : 0,
            display :"44"
          }
        }
      }
    },{
      style: 'activity-7',
      color: '#ec575d',
      id:    7,
      done : true,
      label : {
        short :'walk 555m',
        long  :'walk 555m',
        statstime  :'yesterday'
      },
      val : {
        today : {
          target   : { 
            raw : 0,
            display :"0"
          },
          achieved : {
            raw : 0,
            display :"0"
          }
        },
        yesterday : {
          target   : {
            raw : 0,
            display :"0"
          },
          achieved : {
            raw : 0,
            display :"0"
          }
        }
      }
    }];

what's the best approach to declare this object type? shall I write down the types for every field? Or create a custom type? any other suggestions?

I have this JS object and I want to port it to Typescript:

var items = [{
      style: 'activity-8',
      color: '#a32c62',
      id:    8,
      done : false,
      label : {
        short :'999 m',
        long  :'walk 999m',
        statstime  :'yesterday'
      },
      val : {
        today : {
          target   : { 
            raw : 0,
            display :"11"
          },
          achieved : {
            raw : 0,
            display :"22"
          }
        },
        yesterday : {
          target   : {
            raw : 0,
            display :"33"
          },
          achieved : {
            raw : 0,
            display :"44"
          }
        }
      }
    },{
      style: 'activity-7',
      color: '#ec575d',
      id:    7,
      done : true,
      label : {
        short :'walk 555m',
        long  :'walk 555m',
        statstime  :'yesterday'
      },
      val : {
        today : {
          target   : { 
            raw : 0,
            display :"0"
          },
          achieved : {
            raw : 0,
            display :"0"
          }
        },
        yesterday : {
          target   : {
            raw : 0,
            display :"0"
          },
          achieved : {
            raw : 0,
            display :"0"
          }
        }
      }
    }];

what's the best approach to declare this object type? shall I write down the types for every field? Or create a custom type? any other suggestions?

Share Improve this question asked Oct 12, 2016 at 7:35 PhiceDevPhiceDev 5272 gold badges6 silver badges23 bronze badges 1
  • interface per type should be good enough – harishr Commented Oct 12, 2016 at 7:51
Add a ment  | 

2 Answers 2

Reset to default 11

I don't know if it's the "best" way but I will give you example of my way of doing this.

I will try to explain my general rule not only for nested objects:

For all the properties that are base type (string, number, boolean or some Array of something) you can leave them like this, but for every other plex property/nested object that from now on I will call 'Complex property' (because it makes more sense to me) you make an Interface that will be the type of the property.

Example: In your case the val property is a 'plex' property so let's split it, starting bottom to top.

The smallest plex property in the val property is target, so you make an interface called Target (or ITarget it's not exactly a convention to do that in ts) Target will be something like:

interface Target {
  raw: number,
  display: string
}

You do the same thing for the achieved 'plex' property.

Now you can go one level up. Today property is also a 'plex' one so it has to have a type that probably is going to be some type of interface. Thanks to our previous work that interface will look like:

interface Day {
  target: Target,
  achieved: Achieved
}

You are probably wondering why the interface is called Day and not Today, well the reason is that you have to find out what is the type of the yesterday 'plex' property. As you can see you can see it is the same type as the today property because it has the same properties inside.

So finally the val property that was our goal will have it's own interface that will be something like:

interface Val {
  today: Day,
  yesterday: Day
}

Next you do the same thing for every other 'plex' property.

Now you can use those in your main object which probably will be a class and its properties' types will be those interfaces.

Don't forget that the interface in ts(and not only) is just a 'helping' tool that only helps to organize your code design. Every interface most of the time should has to have a class that implements that interface. And those are the classes that you will use to actually set some values to those properties.

UPDATE (4 years later):

Now when I have more experience with typescript I will still use the same strategy but I'd use the type and not interface to do the pretty much the same job. The interfaces (for me) should be used only if you intend to have a class that would implement them.

If you don't want to extract subtypes (nested fields as separate definitions) because they are used only in that one place, then you can define Interface as follows (code from head)

interface MyItem {
  style: string,
    color: string,
    id: number,
    done: boolean,
    label: {
      short: string,
      long: string,
      statstime: string,
    },
    val: {
      today: {
        target: {
          raw: number,
          display: string
        },
        achieved: {
          raw: number,
          display: string,
        }
      },
      yesterday: {
        target: {
          raw: number,
          display: string,
        },
        achieved: {
          raw: number,
          display: string,
        }
      }
    }
};


// and map your not-typed items table (eg readed from API) to typed
let typedItem: MyItem[] = items.map(item => new MyItem(item));

And use is like this

let items: MyItem[] = [{
  style: 'activity-8',
  color: '#a32c62',
  id: 8,
  done: false,
  label: {
    short: '999 m',
    long: 'walk 999m',
    statstime: 'yesterday'
  },
  val: {
    today: {
      target: {
        raw: 0,
        display: "11"
      },
      achieved: {
        raw: 0,
        display: "22"
      }
    },
    yesterday: {
      target: {
        raw: 0,
        display: "33"
      },
      achieved: {
        raw: 0,
        display: "44"
      }
    }
  }
}, {
  style: 'activity-7',
  color: '#ec575d',
  id: 7,
  done: true,
  label: {
    short: 'walk 555m',
    long: 'walk 555m',
    statstime: 'yesterday'
  },
  val: {
    today: {
      target: {
        raw: 0,
        display: "0"
      },
      achieved: {
        raw: 0,
        display: "0"
      }
    },
    yesterday: {
      target: {
        raw: 0,
        display: "0"
      },
      achieved: {
        raw: 0,
        display: "0"
      }
    }
  }
}];

Here is working example

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1740018849a4185804.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信