简体   繁体   中英

How can I assign out-of-order JSON data to the constructor of a class in Typescript?

I have some json data that I'd like to cast to a typescript object. Please consider the following:

item1 = {'type':'fruit', 'name':'apple', 'color':'red'},
item2 = {'name':'tiger', 'type':'animal'}

The items vary in the number of fields they contain and the order. I also have a class as below:

class Item{
    constructor(...args:any[]){
        this.name = //what should I do here
    }

I'm assuming since I have an unknown number of properties for each item, I should be using (...args:any[]) but feel free to correct me if that is not a good approach. Now, my question is how can I tell the constructor to look for 'name' for instance. If things were in order, I would use args[0], args[1] but since they are not in order, I'm looking for something like args['name']

EDIT:

  1. Items are added as such: firstItem = new Item(//item details here)
  2. The info above is only an example to get the point across. In reality there are thousands of different items all in a JSON string and each item can also have subnodes, so defining a separate class for each is not an option. What all the items have in common is that they all have a 'name'.

It's not very clear from the question, but it sounds like the Item class is used to create a single instance of an item. So should the class not look like:

// class definition
class Item {
    constructor(input:any) {
        if (input) {
            this.name = input.name;
        }
    }
}

//usage
const item1 = {'type':'fruit', 'name':'apple', 'color':'red'},
const item2 = {'name':'tiger', 'type':'animal'}

const item1Instance = new Item(item1);
const item2Instance = new Item(item2);

You can use interfaces to describe the items:

interface ItemData {
    type: string;
    name: string;
}

interface ColorItemData extends ItemData {
    color: string;
}

class Item {
    private type: string;
    private name: string;
    private color: string;

    constructor(data: ItemData | ColorItemData) {
        this.type = data.type;
        this.name = data.name;
        this.color = (data as ColorItemData).color || null;
    }
}

( code in playground )

You can also have a different class per item:

class Item {
    private type: string;
    private name: string;

    constructor(data: ItemData) {
        this.type = data.type;
        this.name = data.name;
    }
}

class ColorItem extends Item {
    private color: string;

    constructor(data: ColorItemData) {
        super(data);
        this.color = data.color;
    }
}

Then:

let item1 = new ColorItem({'type':'fruit', 'name':'apple', 'color':'red'}),
    item2 = new Item({'name':'tiger', 'type':'animal'});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM