1

Suppose I have a class as follows:

class Company {

    name: string;
    url: string;
    address: string

    constructor() {
    }

}

I then retrieve an object from a database which I know contain some or all of the properties of my class eg

{name: "Acme", url: "www.acme.com"}

Is there a way that I can automatically construct my class from the object?

At the moment, I know I can do something like:

    const company = new Company();
    const object = {name: "Acme", url: "www.acme.com"}; // in reality retrieve from database
    for (const key in object) {
        if (key == "name") {
            company.name = object[key];
        }
        if (key == "url") {
            company.url = object[key];
        }

    }

But this is not very elegant and become unwieldy over a larger volume of object properties.

Is there an automatic way to do this?

6
  • have you considered Object.assign ? Commented Jul 21, 2018 at 4:22
  • Yes but I'm not copying object to object, but rather object to class so I'm not sure it would work Commented Jul 21, 2018 at 4:31
  • You only need properties which are present on your class to be copied over? Commented Jul 21, 2018 at 4:34
  • Yes, only properties present in my class Commented Jul 21, 2018 at 4:35
  • Okay, just declaring name: string; doesn't actually do anything. It's erased at compile time. You need to assign a default value to your members, then use Object.keys on your object, and copy things over from your db result object. Commented Jul 21, 2018 at 4:43

1 Answer 1

1

Adapting from your approach:

const company = new Company();
const someObject = { name: "Acme", url: "www.acme.com" };

let legitKeys: Array<keyof Company> = [
    'name','address','url'
];

for (const key in someObject) {
    if (legitKeys.indexOf(key as keyof Company) !== -1) {
        company[key] = someObject[key];   
    }
}

The 'keyof Company'-Type works as a safety-net, so that you can not add strings to the legitKeys array that are not a key of Company by accident.

I feel that there is still a better way, e.g. a more elegant way for writing that if-statement.

To get rid of the compiler-error with noImplicitAny you can use this (still feels like one can do better):

class Company implements IndexSignature { 
    [key: string]: any;
    ...
 }

interface IndexSignature {
    [key: string]: any;
}

const someObject = {
    name: "Acme", url: "www.acme.com"
} as IndexSignature;
Sign up to request clarification or add additional context in comments.

2 Comments

More elegant than what I have but I get a compiler error - "[ts] Element implicitly has an 'any' type because type 'Company' has no index signature."
This occurs if you have noImplicitAny configured as true in your tsconfig. You can either remove that setting or adapt the code to have an Index-Signature, i will update my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.