Iterate over interface properties in TypeScript

JavascriptTypescript

Javascript Problem Overview


I need to map interface properties to objects:

interface Activity {
  id: string,
  title: string,
  body: string,
  json: Object
}

I currently do:

headers: Array<Object> = [
  { text: 'id', value: 'id' },
  { text: 'title', value: 'title' },
  { text: 'body', value: 'body' },
  { text: 'json', value: 'json' }
]

This gets very repetitive. What I would like is something like this:

headers: Array<Object> = Activity.keys.map(key => {
  return { text: key, value: key }
})

Javascript Solutions


Solution 1 - Javascript

You can't, interfaces are only for compile time because javascript doesn't support it.

What you can do is something like:

const Activity = {
    id: "",
    title: "",
    body: "",
    json: {}
}

type Activity = typeof Activity;
const headers: Array<Object> = Object.keys(Activity).map(key => {
    return { text: key, value: key }
});

(code in playground)

Solution 2 - Javascript

If you are okay with having it added during a compile time and you are using TypeScript >= 2.4.1, you can try the way proposed here.

Basically, you should add the ts-transformer-keys dependency, custom transformer, like a basic one and you'll be able to list the properties like this:

import { keys } from 'ts-transformer-keys';

interface Props {
    id: string;
    name: string;
    age: number;
}
const keysOfProps = keys<Props>();

console.log(keysOfProps); // ['id', 'name', 'age']

Solution 3 - Javascript

if you would like to keep the interface ability you can do the following, @Nitzan Tomer is right. Interfaces are part of the type system, hence they are only relevant in compile time as they are omitted in the transpiled code.

class Activity {
    public id: string = '';
    public title: string = '';
    public body: string = '' ;
    public json: Object = {};
}

let activity = new Activity()

const headers: Array<Object> = Object.keys(Activity).map(key => {
    return { text: key, value: key }
});

console.log(JSON.stringify(headers))

Solution 4 - Javascript

This approach might be a bit overkill, but i use it since i need JSON schemas anyway for validating the back end's response structure. Getting the keys from interfaces is just a nice side-effect of converting typescript interfaces into json schemas:

Using a typescript to json schema converter, one could get interfaces keys along with their types. The resulting json objects are large and verbose, so a parsing helper function could come in handy to recursively constructing simpler JS objects the way you want out of them. The good news is that a json schema always has the same structure, so it's easy to navigate.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChrisView Question on Stackoverflow
Solution 1 - JavascriptNitzan TomerView Answer on Stackoverflow
Solution 2 - JavascriptVladyslav ZavalykhatkoView Answer on Stackoverflow
Solution 3 - JavascriptqballerView Answer on Stackoverflow
Solution 4 - JavascriptT. DayyaView Answer on Stackoverflow