1

I'm pretty new with these languages and I'm sure it's not so complicated but could not find how to walk through class instance variables dynamically.

I'm trying to display instance's variables in a table using Angular. I'd like to write a single function that will work with any class.

Let's say I have a workbook class:

export class workbookEntity {
    public name: string;
    public creationDate: string;

    constructor() {
        this.name = 'my work book name';
        this.creationDate = '2018/01/26';
    }
}

And let's say I want to get the names and values of the variables of an instance of this class in another class' function:

export class showClassComponent {
    // some code here

    whenSubmitedInHtmlForm(className: string): void {
        // do something to walk through instance
        // with className parameter = 'workbookEntity'
    }

    // more code there
}

How would you walk through the instance to get each variable's name and value to get something like this?

[
    {
        name: 'name',
        value: 'my work book name'
    },
    {
        name: 'creationDate',
        value: '2018/01/26'
    }
]
l_r
  • 1,060
  • 12
  • 23
  • You should create a service for work like this. Otherwise you would need to inject the component to get access to its variables. – David Aguirre Jan 26 '18 at 19:57
  • What are you really trying to do? – Sébastien Jan 26 '18 at 20:04
  • Yea, create a service with a Behavior Subject that is updated by a given instance. Then just subscribe to that Subject from the component that will utilize the info. – David Aguirre Jan 26 '18 at 20:29
  • @Sébastien: I'm trying to display different objects in a cdk table. The table has 2 columns: Variable & Value. The list of the objects names is displayed. Each time the user select an object name, all instances and their variables and values are displayed in the 2 columns of the table.I don't want to write a cdk source for each type of objects. I'd like to have a single function that will work with any object. – l_r Jan 28 '18 at 17:08

2 Answers2

0

There's no concept of reflection, so much in Typescript, so you can't neccessarily do a type lookup. But you might be able to do something along the lines of...

export class showClassComponent {
    var classes = [ { name: 'workBookEntity', value: new WorkBookEntity() }]

    whenSubmitedInHtmlForm(className: string): void {
        let c = classes.filter(class => class.name == className)[0];
        if(c) {
            let ret = [];

            for (var key in c) {
                if (c.hasOwnProperty(key)) {
                    ret.push({ name: key, value: c[key] });
                }
            }

            return ret;
        }
    }

    // more code there
}
Barry Tormey
  • 2,966
  • 4
  • 35
  • 55
0

If you want to be able to retain accurate type information, you can create a pick utility function and then just import it into your class module wherever you need to use it.

let workBook = new WorkbookEntity();

export function pick<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
  let newObj = {} as Pick<T, K>;
  for (const key of keys) {
    newObj[key] = obj[key];
  }
  return newObj;
}

console.log(pick(workBook, ['name', 'creationDate']));

// log: { name: 'my work book name', creationDate: '2018/01/26' }

Then you can import the first function into another utility function if you to be able to handle multiple objects.

export function pickObjects<T extends object, K extends keyof T>
  (objects: T[], keys: K[]): Pick<T, K>[] {
  return objects.reduce((result, obj) => [...result, pick(obj, keys)], []);
}

let workbooks = pickObjects([workBook, workBook2], ['name']);
workbooks[0].name // this exists
workbooks[0].age // Typescript error. 

The editor will show that age doesn't exist since we didn't pick it

Anthony
  • 13
  • 1
  • 3